问题描述
我将尝试忽略其他细节,并使其简短化:
I will try to ignore other details and make it short:
@Entity
public class User
@UniqueEmail
@Column(unique = true)
private String email;
}
@Component
public class UniqueEmailValidatior implements ConstraintValidator<UniqueEmail,String>, InitializingBean {
@Autowired private UserService userService;
@Override
public void initialize(UniqueEmail constraintAnnotation) {
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if(userService == null) throw new IllegalStateException();
if(value == null) return false;
return !userService.isEmailExisted(value);
}
}
当在Spring中进行验证(Spring MVC @Valid
或使用@Autowire
注入Validator
)时,这将起作用,一切都会好起来的.但是,一旦我使用Spring Data JPA保存了实体,
This will work when the validation is made in Spring (Spring MVC @Valid
or inject the Validator
using @Autowire
), everything will be fine.But as soon as I save the entity using Spring Data JPA:
User save = userRepository.save(newUser);
Hibernate将尝试实例化一个新的UniqueEmailValidatior
而不注入UserService
bean.因此,如何使Hibernate在不实例化新组件的情况下使用我的UniqueEmailValidatior
组件.我可以使用spring.jpa.properties.javax.persistence.validation.mode=none
禁用休眠验证,但我希望还有另一种方法
Hibernate will try to instantiate a new UniqueEmailValidatior
without inject the UserService
bean.So how can I make Hibernate to use my UniqueEmailValidatior
component without it instantiate a new one.I could disable hibernate validation using spring.jpa.properties.javax.persistence.validation.mode=none
but I hope there is another way
更新:这是我的UserService:
Update: Here is my UserService:
@Autowired private Validator validator;
@Transactional
public SimpleUserDTO newUser(UserRegisterDTO user) {
validator.validate(user);
System.out.println("This passes");
User newUser = new User(user.getUsername(),
passwordEncoder.encode(user.getPassword()),user.getEmail(),
"USER",
user.getAvatar());
User save = userRepository.save(newUser);
System.out.println("This won't pass");
return ....
}
推荐答案
我希望Spring Boot可以将现有的验证器连接到EntityManager
,显然不会.
I would expect that Spring Boot would wire the existing validator to the EntityManager
apparently it doesn't.
您可以使用HibernatePropertiesCustomizer
并将属性添加到现有的EntityManagerFactoryBuilder
并注册Validator
.
You can use a HibernatePropertiesCustomizer
and add properties to the existing EntityManagerFactoryBuilder
and register the Validator
.
注意::这里我假设您正在使用Spring Boot 2.0
NOTE: I'm assuming here that you are using Spring Boot 2.0
@Component
public class ValidatorAddingCustomizer implements HibernatePropertiesCustomizer {
private final ObjectProvider<javax.validation.Validator> provider;
public ValidatorAddingCustomizer(ObjectProvider<javax.validation.Validator> provider) {
this.provider=provider;
}
public void customize(Map<String, Object> hibernateProperties) {
Validator validator = provider.getIfUnique();
if (validator != null) {
hibernateProperties.put("javax.persistence.validation.factory", validator);
}
}
}
类似的事情应该将现有的验证器与休眠连接,并利用自动连接.
Something like this should wire the existing validator with hibernate and with that it will make use of auto wiring.
注意::您不需要在验证器上使用@Component
,在返回Validator
的实例之前,自动装配已内置到验证器工厂中.
NOTE: You don't need to use @Component
on the validator the autowiring is build into the validator factory before returning the instance of the Validator
.
这篇关于Spring Boot-Hibernate自定义约束不会注入服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!