我将尝试忽略其他细节并将其简短化:
@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或注入Validatorusing @Autowire)时,这将起作用,一切都会好起来的。但是,一旦我使用Spring Data JPA保存了实体:
@Valid
Validator
@Autowire
User save = userRepository.save(newUser);
Hibernate将尝试在UniqueEmailValidatior不注入UserServicebean的情况下实例化一个新对象。因此,如何使Hibernate在UniqueEmailValidatior不实例化新组件的情况下使用我的组件。我可以使用禁用hibernate验证,spring.jpa.properties.javax.persistence.validation.mode=none但我希望有另一种方法
UniqueEmailValidatior
UserService
spring.jpa.properties.javax.persistence.validation.mode=none
更新:这是我的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显然没有的连接器。
EntityManager
您可以使用HibernatePropertiesCustomizer并向现有属性添加属性,EntityManagerFactoryBuilder然后注册Validator。
HibernatePropertiesCustomizer
EntityManagerFactoryBuilder
注意: 我在这里假设您正在使用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); } } }
这样的事情应该使现有的验证器与hibernate连接,并利用自动连接。
注意: 您不需要@Component在验证器上使用自动装配内置到验证器工厂中,然后再返回的实例Validator。
@Component