我需要通过使用Spring存储库对对象执行验证。我正在尝试将Spring repo bean注入ConstraintValidator中。当控制器中发生验证时,验证器将按预期与Spring bean一起注入。但是,当在保存实体之前执行了验证(由持久性管理器执行)时,回购依赖项为null,我得到了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]
.....