问题描述
我遇到的是Spring Boot与Hibernate Validation之前提到的问题,其中自定义Constraint Validators内部的依赖项自动装配无法正常工作.通过我自己的调试,我注意到,当进行实体级验证时,与Hibernate对表单提交执行Bean验证时相比,Hibernate加载了一个不同的ConstraintValidatorManager.后者工作正常,前者导致自定义约束验证器的相关性为空.似乎Hibernate正在从根上下文中加载一个管理器,并从servlet上下文中加载一个管理器.这将解释Hibernate不了解自定义约束验证器中自动关联的依赖项的存在.但是,如果这是真的,我不知道发生了什么,或者不知道如何使Hibernate/JPA知道Spring上下文及其bean.
I am facing an issue that has been mentioned before with Spring Boot vs. Hibernate Validation, where autowiring of dependencies inside custom Constraint Validators is not working. From my own debugging, I have noticed that when entity-level validation occurs, Hibernate loads a different ConstraintValidatorManager compared to when Hibernate is performing bean validation for form submits. The latter works fine, the former leads to dependencies of the custom Constraint Validator being null. It seems as if Hibernate is loading one manager from the root context and one from the servlet context. This would explain Hibernate not having any knowledge of the existence of the dependencies autowired in the custom Constraint Validator. If this is true however, I do not understand what is going on, or how to make Hibernate/JPA aware of the Spring context and it's beans.
我希望有人可以指出正确的方向吗?我已经尝试了以下所有答案,以及更多其他答案(例如,不同的库版本,配置方法,通过utils类加载静态bean等):
I am hoping someone could point me in the right direction? I have tried all of the below answers, and much more (e.g. different library versions, configuration methods, static bean loading through a utils class, etc.):
在ConstraintValidator中注入带有Spring 4和消息的存储库插值配置
我也已经多次浏览过Spring Boot的参考指南,没有多大运气.有几种情况提到它们的Hibernate验证在常规bean提交以及实体持久期间均能正常工作.不幸的是,我似乎无法检索他们使用的确切(Java)配置,但似乎他们正在使用默认配置.我开始怀疑这是否是特定于Spring Boot的问题(尽管已经指出,Spring Validation和Hibernate Validation的组合应该可以立即使用).
Also I have been through the Reference guide for Spring Boot specifically several times, without much luck. There are several cases that mention their Hibernate validation working fine, both for regular bean submits, as well as during entity persisting. Unfortunately, I seem unable to retrieve their exact (Java) configuration they used, but it seems they are using default configuration. I am starting to wonder if this is a specific Spring Boot issue (although it is stated a combination of Spring Validation and Hibernate Validation should work out-of-the-box).
添加像下面的bean这样的东西不能解决问题(默认工厂是Course的SpringConstraintValidatorFactory):
Adding anything like below bean does not solve the issue (default factory being SpringConstraintValidatorFactory ofcourse):
@Bean
public LocalValidatorFactoryBean validator()
{
LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
bean.setValidationMessageSource(messageSource());
return bean;
}
也没有为Hibernate验证器添加bean定义,例如:
Nor does including a bean definition for a Hibernate validator as such:
有很多不同的方式来加载和注入所需的bean,但是如果Hibernate根本不知道在上下文中加载的bean(因为它使用的是不同的上下文?),该如何进行?
There are many different ways of loading and injecting the desired bean, but if Hibernate is not at all aware of the beans loaded in the context (because it is using a different context?), how to proceed?
谢谢.
更新:Gradle文件
UPDATE: Gradle file
buildscript {
ext {
springBootVersion = '2.1.5.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = '<hidden>'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
jcenter()
}
dependencies {
implementation('org.springframework.boot:spring-boot-starter-web')
implementation('org.springframework.boot:spring-boot-starter-tomcat:2.1.5.RELEASE')
implementation('org.springframework.boot:spring-boot-starter-thymeleaf')
implementation('org.springframework.boot:spring-boot-starter-security')
implementation('org.springframework.boot:spring-boot-starter-data-jpa')
implementation('org.springframework.boot:spring-boot-starter-mail')
implementation('org.springframework.session:spring-session-core')
annotationProcessor('org.springframework.boot:spring-boot-configuration-processor')
implementation('org.postgresql:postgresql')
// https://mvnrepository.com/artifact/org.jboss.aerogear/aerogear-otp-java
implementation('org.jboss.aerogear:aerogear-otp-java:1.0.0')
implementation('com.github.mkopylec:recaptcha-spring-boot-starter:2.2.0')
implementation('nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:2.0.5')
implementation('org.thymeleaf.extras:thymeleaf-extras-springsecurity3:3.0.4.RELEASE')
implementation('javax.enterprise:cdi-api:2.0')
runtimeOnly('org.springframework.boot:spring-boot-devtools')
testImplementation('org.springframework.boot:spring-boot-starter-test')
testImplementation('org.springframework.security:spring-security-test')
testImplementation 'org.mockito:mockito-core:2.27.0'
}
推荐答案
有一种方法可以通过设置javax.persistence.validation.factory
There is a way to tell Hibernate to use the same validator by setting javax.persistence.validation.factory
@Configuration
@Lazy
class SpringValidatorConfiguration {
@Bean
@Lazy
public HibernatePropertiesCustomizer hibernatePropertiesCustomizer(final Validator validator) {
return new HibernatePropertiesCustomizer() {
@Override
public void customize(Map<String, Object> hibernateProperties) {
hibernateProperties.put("javax.persistence.validation.factory", validator);
}
};
}
}
那样,一切正常.
这篇关于使用不同的ConstraintValidatorManager的Spring Boot中的Hibernate Validator的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!