当前位置: 首页 > 知识库问答 >
问题:

Spring Boot-Hibernate自定义约束不注入服务

百里光熙
2023-03-14

我将尽量忽略其他细节,并将其简短化:

@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注入验证器),这将起作用,一切都会很好。但一旦我使用Spring Data JPA保存实体:

User save = userRepository.save(newUser);

HiberNate将尝试实例化一个新的UniqueEmail Validatior,而不会注入UserServicebean。所以我如何让HiberNate使用我的UniqueEmail Validatior组件,而不会实例化一个新的组件。我可以使用spring.jpa.properties.javax.persistence.validation.mode=无禁用hiberNate验证,但我希望有另一种方法

更新:以下是我的用户服务:

   @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 ....
    }

共有3个答案

赵才俊
2023-03-14

答案是相当大的,请在这里查看这篇文章来帮助你。这应该有助于你开始。

使用Autowired spring服务测试定制验证器

问题是hibernate根本不知道spring的定义。然而,您可以让实体知道任何类型的javax。验证类型。希望这有帮助。

拓拔元徽
2023-03-14

要将Spring bean注入您的ConstraintValidator,您需要一个特定的ConstraintValidatorFactory,它应该在验证工厂的初始化时传递。

大致如下:

ValidatorFactory validatorFactory = Validation.byDefaultProvider()
    .configure()
    .constraintValidatorFactory( new MySpringAwareConstraintValidatorFactory( mySpringContext ) )
    .build();

MySpringAware ConstraintValidatorFactory是一个ConstraintValidatorFactory,它将bean注入到您的ConstraintValidator中。

我怀疑Spring Data使用的ValidatorFactory在创建验证器时没有注入验证器,这是不幸的。

我想你应该能够覆盖它。或者更好的是,你应该打开一个针对Spring Boot/Spring Data的问题,这样他们就可以正确地注入ConstraintValidators,因为这是我们连续第二次在SO上遇到这个问题。

柳晔
2023-03-14

我希望Spring Boot会将现有的验证器连接到EntityManager,显然它没有。

您可以使用hibernateProperties自定义程序,向现有的EntityManagerFactoryBuilder添加属性,并注册验证程序

注意:我在这里假设您使用的是SpringBoot2.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,在返回验证器的实例之前,自动连线是构建在验证器工厂中的。

 类似资料:
  • 我已经为此斗争了好几天,我已经阅读了这里的所有讨论,但没有解决方案...... 我有一个自定义约束… 独一无二.java 这是由UniqueConstraintValidator使用的.java 现在,我的模型有这个注释,我需要在其中验证字段的唯一性 现在,我知道自定义注释在更新现有对象时不起作用,但是现在我需要了解它是如何工作的。假设我们想要添加一个新对象。 当我试图保存一个已经存在的值时,我得

  • 我在项目中使用bean验证,我想为现有的约束注释编写一个自定义验证器。 例如,我有一个类,它表示一个名为CustomDateTime的日期/时间。在使用此类作为例如出生日期的类中,我想用过去的日期对字段进行注释: 然后,我通过实现ConstraintValidator创建一个自定义验证器 我知道您通常会创建这样的单独注释: 但对我来说,这似乎是双重代码;-) 如何注册要与一起使用的自定义验证器?

  • 我试图创建自定义注释来检查唯一的字段值。例如,检查唯一的电子邮件地址等。 但无法自动关联“customerDAO”对象。它抛出异常组织。springframework。网状物util。NestedServletException:请求处理失败;嵌套的异常是javax。验证。ValidationException:isValid调用期间发生意外异常。 我在哪里犯错?请建议。 顾客JAVA 唯一的JA

  • 我有一个名为的下拉字段,其中包含电话、电子邮件等值,还有一个名为的输入字段。如果选择了下拉值,我想验证输入字段的有效电子邮件地址。。。 我试图创建一个自定义约束,将验证字段对电子邮件正则表达式,如果字段将具有值 我有以下自定义约束的代码 验证器就像 问题是它没有在表单上触发...我使用模型对话框,其中要验证的bean被呈现 参考:使用Hibernate验证器进行跨域验证(JSR 303) 期待您的

  • TLDR:我想要在单独的模块中单独的自定义bean验证定义及其ConstraintValidator实现。为此,我必须使用ConstraintMmap手动注册。它适用于带注释的类。但是定义的绑定不共享/可用于通过validation-constraints.xml.定义的验证如何修复?我试图调试它,以找出它在哪里初始化以及为什么会出现问题,但初始化这些远非易事。 动机: 一) 分离模块:如果API

  • 我有一个自定义注释@UniqueModel,它由ConstraintValidator验证: 问题是,我需要在调用存储库的safe()-方法之前进行验证,否则字段注入将无法工作。 因此,我创建了一个带有@Valid注释的委托方法,以便在以下情况之前强制进行唯一验证: 不幸的是,这不起作用,似乎@Valid注释被Spring忽略了。 我如何确保验证的正确时间?