首页 > 解决方案 > Spring Boot 1.3.8 + 休眠。JPA 端 ConstraintValidator 的双重初始化

问题描述

这个问题经常出现,但我提出了新的水平(看起来)。已经研究了几个小时。

有一个带有休眠功能的弹簧靴(1.3.8 版本)。

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>9</java.version>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.8.RELEASE</version>
    </parent>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</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-data-jpa</artifactId>
        </dependency>

使用 bean 注入形成了一个 ConstraintValidator,我已按类型将其绑定到实体:@Target(ElementType.TYPE)

在控制器方面,我使用了 @Valid 注释。

这就是我得到的(特别将'isValid'标记为日志): Controller -> @Valid -> Logger 告诉 isValid 被调用(验证器的'this'给出一个对象地址)

在此之后有一个保存实体的调用:Controller -> Service -> JPA 从这一点我看到再次调用了 isValid,碰到了自动装配 bean 的空引用。记录器显示验证器对象不同,并为“this”输出显示不同的内存块。

当我使用构造函数注入删除默认构造函数时,我看到了更清晰的画面:hibernate.newInstance 未能找到默认构造函数。

所以罪魁祸首似乎是 JPA,它试图在保存状态下创建和验证实体,创建一个单独的验证器实例。

而这件事只有在我对实体进行自定义验证时才相关。将其划分为 entity-dto,在 DTO 上进行验证,一切都像魅力一样工作。

尝试了来自网络的建议来定义验证器和其他东西,但没有任何效果。

有人可以建议如何在没有 DTO 的情况下执行此操作(讨厌重复 entity-dto)吗?


这里有一个有趣的事情要补充。经过几次尝试,设法使用静态和构造函数 autowire 保存了 bean 注入(不知道我昨天做错了什么)并且 isValid 开始通过。但是现在我在 saveAndFlush 上得到一个“null id”异常,这是由对 JPA 的通用 findByIpAndIdNot 的调用引起的。

我显然对此越来越困惑,因为这开始失去意义。在调用之前,我验证了 DAO 对象是否相同、实体 - 相同等等,但此时我突然捕捉到了一个空指针。

尝试从 JDK 9 切换到 8。没有。

标签: javahibernatevalidationspring-bootspring-data-jpa

解决方案


推荐阅读