配置Spring验证和休眠验证

时间:2019-06-26 23:55:52

标签: hibernate spring-boot validation dependency-injection spring-data-jpa

问题已在此处解决,但对我不起作用(我猜不是春季启动版本)this

尝试编码自定义约束验证器,以在保留之前检查帐户电子邮件是否存在。

@Email
@NotNull
@NotBlank
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UniqueCompteEmailValidator.class)
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
public @interface UniqueCompteEmail {

    String message() default "{com.mssmfactory.bacsimulator.uniquecompteemail.message}";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

// --------------------------------------------- -----------------------------

public class UniqueCompteEmailValidator implements ConstraintValidator<UniqueCompteEmail, String> {

    @Autowired
    private CompteRepository compteRepository;

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return value != null && this.compteRepository.findByEmail(value) == null;
    }
}

// --------------------------------------------- -----------------------------

@Configuration
public class OtherConfigurations {

    //----

    @Bean
    public Validator validator(@Autowired AutowireCapableBeanFactory autowireCapableBeanFactory) {
        ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class).configure()
                .constraintValidatorFactory(new SpringConstraintValidatorFactory(autowireCapableBeanFactory))
                .buildValidatorFactory();
        Validator validator = validatorFactory.getValidator();

        return validator;
    }
}

// --------------------------------------------- -----------------------------

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.mssmfactory</groupId>
    <artifactId>bacsimulator</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>bacsimulator</name>
    <description>BAC Simulator</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jersey</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

我的问题是私有CompteRepository compteRepository始终包含null,从我的堆栈跟踪中,我可以看到它正在通过hibernate-validation实例化,而不是通过spring实例化并由hibernate使用。

有什么想法吗?

2 个答案:

答案 0 :(得分:0)

您面临的问题是因为@Autowired注释在自动装配CompteRepository.class时不起作用。您可以在验证类中自动装配组件,但要确保使用spring来创建组件。验证器bean,否则该注入不会像使用valdiation工厂(休眠验证器作为参考实现)手动创建验证器bean一样起作用。不会将依赖项注入ConstraintValidator实例

因此,您不能使用验证器工厂来创建验证器实例,而要自动将其装配好,一切都会正常工作。

@AutoWired
Validator validator;
...

validator.validate(book);

答案 1 :(得分:0)

通过@Component类更改了休眠的bean验证器工厂,现在效果很好

@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);
        }
    }
}