Spring Boot-Hibernate自定义约束不会注入服务 [英] Spring Boot - Hibernate custom constraint doesn't inject Service

查看:263
本文介绍了Spring Boot-Hibernate自定义约束不会注入服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将尝试忽略其他细节,并使其简短化:

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自定义约束不会注入服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆