Мне нужно выполнить проверку объекта, используя репозиторий Spring.Я пытаюсь внедрить компонент репо Spring в ConstraintValidator.Когда проверка происходит в контроллере, валидатор внедряется, как и ожидалось, с компонентом Spring.Но когда проверка выполняется (менеджером постоянства) перед сохранением сущности, зависимость репо становится нулевой, и я получаю NPE.
Я прочитал много постов об этой проблеме, но, похоже, они касаются более ранних версий Spring.Я использую Spring Boot 2.1 (Spring Framework 5.1).
Вот мой код:
public class OrderItemDeleteValidator
implements ConstraintValidator<OrderItemDelete, Order> {
@Autowired
public OrderItemRepository orderItemRepo;
@Override
public void initialize(OrderMandatesDelete o) {
//Tried this line to no avail based on one of many posts
//SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
/**
Invalid if items have been deleted from the order. Otherwise valid
**/
@Override
public boolean isValid(Order order, ConstraintValidatorContext context) {
if (order.getId() == null) {
// An order is new so all line items are new.
return true;
}
List<OrderItems> originalOrderItems = orderItemRepo.findByOrderId(order.getId());
// code to compare original order items to current order items
// return false if current order is missing items from
// original order items. Otherwise return true
}
}
Я добавил ведение журнала и вижу, что третий вызов валидатора сообщает об отсутствии значения для orderItemRepo
.Не знаете, почему есть три вызова?
На основе нескольких сообщений, таких как https://stackoverflow.com/a/30715908/1706691 и https://stackoverflow.com/a/47246376/1706691, Я попытался настроить свою конфигурацию БД следующим образом:
@Autowired
Validator v;
@Bean
@Primary
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder, Validator v) {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("javax.persistence.validation.factory", v);
LocalContainerEntityManagerFactoryBean l = builder
.dataSource(dataSource())
.packages("com.example.domain")
.persistenceUnit("main")
.properties(properties)
.build();
return l;
}
Но это приводит к бесконечной проверке, вызывающей переполнение стека:
java.lang.StackOverflowError: null
at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_192]
at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[na:1.8.0_192]
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[na:1.8.0_192]
at java.net.URLClassLoader.defineClass(URLClassLoader.java:468) ~[na:1.8.0_192]
at java.net.URLClassLoader.access$100(URLClassLoader.java:74) ~[na:1.8.0_192]
at java.net.URLClassLoader$1.run(URLClassLoader.java:369) ~[na:1.8.0_192]
at java.net.URLClassLoader$1.run(URLClassLoader.java:363) ~[na:1.8.0_192]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_192]
at java.net.URLClassLoader.findClass(URLClassLoader.java:362) ~[na:1.8.0_192]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_192]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) ~[na:1.8.0_192]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_192]
at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_192]
at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[na:1.8.0_192]
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[na:1.8.0_192]
at java.net.URLClassLoader.defineClass(URLClassLoader.java:468) ~[na:1.8.0_192]
at java.net.URLClassLoader.access$100(URLClassLoader.java:74) ~[na:1.8.0_192]
at java.net.URLClassLoader$1.run(URLClassLoader.java:369) ~[na:1.8.0_192]
at java.net.URLClassLoader$1.run(URLClassLoader.java:363) ~[na:1.8.0_192]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_192]
at java.net.URLClassLoader.findClass(URLClassLoader.java:362) ~[na:1.8.0_192]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_192]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) ~[na:1.8.0_192]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_192]
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1505) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.query.Query.getResultList(Query.java:135) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution.doExecute(JpaQueryExecution.java:129) ~[spring-data-jpa-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:91) ~[spring-data-jpa-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:136) ~[spring-data-jpa-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:125) ~[spring-data-jpa-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:605) ~[spring-data-commons-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.lambda$invoke$3(RepositoryFactorySupport.java:595) ~[spring-data-commons-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:595) ~[spring-data-commons-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59) ~[spring-data-commons-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294) ~[spring-tx-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:117) ~[spring-data-jpa-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61) ~[spring-data-commons-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.1.2.RELEASE.jar:5.1.2.RELEASE]
.....