Java 冬眠';s ddl auto=验证和列默认值

Java 冬眠';s ddl auto=验证和列默认值,java,hibernate,Java,Hibernate,如何让Hibernate在启动时验证列默认值(通过Hibernate.hbm2ddl.auto=validate) 更新 从我的分析中,我只看到Hibernate在评估列的类型,仅此而已。请参阅:org.hibernate.tool.schema.internal.AbstractSchemaValidator.validateTable() 如果我想验证诸如默认值之类的信息,我可能必须编写自己的代码,遍历Hibernate实体的元模型和数据库表 主要问题: 当Hibernate实体中的

如何让Hibernate在启动时验证列默认值(通过
Hibernate.hbm2ddl.auto=validate

更新

  • 从我的分析中,我只看到Hibernate在评估列的类型,仅此而已。请参阅:
    org.hibernate.tool.schema.internal.AbstractSchemaValidator.validateTable()
  • 如果我想验证诸如默认值之类的信息,我可能必须编写自己的代码,遍历Hibernate实体的元模型和数据库表

主要问题:

  • 当Hibernate实体中的默认值定义与实际数据库的默认值设置不匹配时,Hibernate不会在启动期间抛出错误。我希望看到一个错误。我如何确保它被抛出
  • 当列的数据类型不匹配时,Hibernate会在启动时抛出一个错误(这是一件好事)
下面我将解释所有细节您可能只需查看代码片段,就可以理解我想要表达的内容。


详细信息:MariaDB命令行

我通过以下方式创建了一个MariaDB表:

CREATE TABLE `person2` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` text NOT NULL,
  `age` int(11) DEFAULT 27,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
当我使用mysql命令行并手动运行insert语句时,新记录的
age
设置为27(预期行为):

我还可以显式提供年龄,并且它接受提供的值(预期行为):


详细信息:休眠

我正在使用Spring/Hibernate,我创建了以下类来映射到
person2
表:

import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.Type;
import javax.persistence.*;

@Entity
@Table(name = "person2")
@DynamicInsert
public class Person2 {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Type(type = "text")
    @Column(nullable = false)
    private String name;

    @ColumnDefault("27")
    @Column
    private Integer age;

    // Normal getters/setters:

    public void setName(String val) {
        this.name = val;
    }

    public String getName() {
        return this.name;
    }

    public void setAge(Integer val) {
        this.age = val;
    }

    public Integer getAge() {
        return this.age;
    }
}
为了在Spring启动时生成一些测试数据,我有以下几点:

@Configuration
public class DatabaseLoader {

    @Order(1)
    @Bean
    public CommandLineRunner createTestData(Person2Repository person2Repository) {
        Person2 person2 = new Person2();
        person2.setName("hibernate: Bob 10");
        person2Repository.save(person2);

        ...

        return args -> {
        };
    }
}
乍一看,一切都很好:一行被添加到数据库中,右边的
名称
年龄
=27


休眠阴性测试:

我想确保Hibernate的
Hibernate.hbm2ddl.auto=validate
工作正常。因此,我做了以下工作:

@Configuration
public class DatabaseLoader {

    @Order(1)
    @Bean
    public CommandLineRunner createTestData(Person2Repository person2Repository) {
        Person2 person2 = new Person2();
        person2.setName("hibernate: Bob 10");
        person2Repository.save(person2);

        ...

        return args -> {
        };
    }
}
我在entity类中将age的类型从Integer更改为Long:

@Entity
@Table(name = "person2")
@DynamicInsert
public class Person2 {
    ...

    @ColumnDefault("27")
    @Column
    private Long age;
}
正如预期的那样,Hibernate引发了以下错误:

  • 原因:javax.persistence.PersistenceException:[PersistenceUnit:default]无法构建Hibernate SessionFactory;嵌套异常为org.hibernate.tool.schema.spi.SchemaManagementException:模式验证:表[person2]中的[age]列中遇到错误的列类型;找到[int(类型#整型)],但应为[bigint(类型#整型)]
酷,我想抛出那个错误。然后我想测试另一个场景:导致列默认值设置不匹配。但是,当我进行如下所示的修改时,启动时没有出现错误(这不是我所期望的):

Hibernate在输入错误时甚至没有抛出错误,但输入了一个虚假的默认值(非数字):

所以我想让我们试试设置默认值的
columnDefinition
技术。同样,我使用了一个伪值(见下文),Hibernate没有抛出错误(这不是我所期望的):



我做错了什么?

首先,您应该知道默认值是如何在数据库列中使用的<代码>默认值
在将记录保存到列中时,如果列中没有值,则会在该列中设置值,这意味着如果您正在保存记录,并且某些属性或列没有值,并且您已配置默认值,则在这种情况下,默认值会设置为该列,否则会在保存记录的时间

假设您有column1,默认值为10,那么在将记录写入表时
如果column1不为空,则写入column1的值,否则写入默认值10

更改为
创建
更新
,然后查看将发生什么。
@Entity
@Table(name = "person2")
@DynamicInsert
public class Person2 {
    ...

    @ColumnDefault("27")
    @Column
    private Long age;
}
public class Person2 {
    ...

    @ColumnDefault("999")
    @Column
    private Integer age;
}
public class Person2 {
    ...

    @ColumnDefault("asdf")
    @Column
    private Integer age;
}
public class Person2 {
    ...

    @Column(columnDefinition = "asdf")
    private Integer age;
}