[Hibernate] Hibernate配制项之hibernate.hbm2ddl.auto

阎辰钊
2023-12-01

Hibernate配制项之hibernate.hbm2ddl.auto

前言

我们在本地作开发时,经常会定义好实体,继而在相应的数据库中建表。而这样建表继烦琐,浪费时间,又容易出错。而Hibernate的hibernate.hbm2ddl.auto会帮助我们根据定义好的实体,自动创建,更新,验证数据库表。hibernate.hbm2ddl.auto有好几个选项,接下来我们依次介绍。

hibernate.hbm2ddl.auto选项

none(默认)
在Hiberante启动时,不会执行任何操作。

create-only
在Hibernate启动时,对实体仅会执行建表语句,即使实体对应的表已经存在了,也会重复执行建表语句。

情景一
存在如下实体

@Entity
public class Event {

    @Id
    @Column(name = "EVENT_ID")
    private Long id;

    private String title;

    @Column(name = "EVENT_DATE")
    private Date date;

    private int version;

    // 省略getter setter
 }

Hibernate在启动时,不管实体对应的表存不存在,都会执行建表语句

    create table Event (
       EVENT_ID bigint not null,
        EVENT_DATE datetime(6),
        title varchar(255),
        version integer not null,
        primary key (EVENT_ID)
    ) engine=InnoDB

drop
在Hiberante启动时,对实体对应的表执行删除语句,即使实体不存在对应的表,都会执行表删除语句。
情景一
存在如下实体

@Entity
public class Event {

    @Id
    @Column(name = "EVENT_ID")
    private Long id;

    private String title;

    @Column(name = "EVENT_DATE")
    private Date date;

    private int version;

    // 省略getter setter
 }

Hibernate在启动时,不管对应的表存不存在,都会执行删除语句。

drop table if exists Event

create
在Hiberante启动时,对实体对应的表执行删除语句,然后再执行建表语句。

情景一
存在如下实体

@Entity
public class Event {

    @Id
    @Column(name = "EVENT_ID")
    private Long id;

    private String title;

    @Column(name = "EVENT_DATE")
    private Date date;

    private int version;

    // 省略getter setter
 }

在Hibernate启动时,不管数据库中对应的表存不存在
都要先执行删除语句

drop table if exists Event

在执行建表语句

    create table Event (
       EVENT_ID bigint not null,
        EVENT_DATE datetime(6),
        title varchar(255),
        version integer not null,
        primary key (EVENT_ID)
    ) engine=InnoDB

create-drop
在Hibernate启动时,对实体对应的表执行删除语句,然后执行建表语句。在Hibernate关闭时,实体对应的表执行删除语句。
情景一
存在如下实体

@Entity
public class Event {

    @Id
    @Column(name = "EVENT_ID")
    private Long id;

    private String title;

    @Column(name = "EVENT_DATE")
    private Date date;

    private int version;

    // 省略getter setter
 }

Hibernate在启动时会先删除对应的表

 drop table if exists Event

重新创建对应的表

    create table Event (
       EVENT_ID bigint not null,
        EVENT_DATE datetime(6),
        title varchar(255),
        version integer not null,
        primary key (EVENT_ID)
    ) engine=InnoDB

在Hibernate关闭时,会删除对应的表

drop table if exists Event

validate
对实体和对应的表进行校验。

情景一
如果实体中的属性在对应的数据库表中不存在,则会抛出异常。
如对应的实体如下:

@Entity
public class Event {

    @Id
    @Column(name = "EVENT_ID")
    private Long id;

    private String title;

    @Column(name = "EVENT_DATE")
    private Date date;

    private int version;

    // 省略getter setter
 }

数据库中对应的表如下:

CREATE TABLE `EVENTS` (
  `EVENT_ID` bigint(20) NOT NULL,
  `EVENT_DATE` date DEFAULT NULL,
  `title` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`EVENT_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

表中缺少了version字段,Hibernate在启动时则会抛出异常。

org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing column [version] in table [EVENT]

情景二
如对应的实体如下:

@Entity
public class Event {

    @Id
    @Column(name = "EVENT_ID")
    private Long id;

    private String title;

    @Column(name = "EVENT_DATE")
    private Date date;

    private int version;

    // 省略getter setter
 }

但是在数据库不存在对应的表,Hibernate在启动时则会抛出如下异常:

org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing table [Event]

update
实体对应的表如果不存在则会创建。如果实体中新增加了字段,会在相应的表中增加一列。

情景一
存在如下实体

@Entity
public class Event {

    @Id
    @Column(name = "EVENT_ID")
    private Long id;

    private String title;

    @Column(name = "EVENT_DATE")
    private Date date;

    private int version;

    // 省略getter setter
 }

在数据库中不存在对应的表,Hibernate在启动时则会执行建表语句。

create table EVENT (
   EVENT_ID bigint not null,
    EVENT_DATE date,
    title varchar(255),
    version integer,
    primary key (EVENT_ID)
) engine=InnoDB

情况二
存在如下实体

@Entity
public class Event {

    @Id
    @Column(name = "EVENT_ID")
    private Long id;

    private String title;

    @Column(name = "EVENT_DATE")
    private Date date;

    private int version;

    // 省略getter setter
 }

在数据库中存在对应的表,但是缺失了version字段。

CREATE TABLE `EVENT` (
  `EVENT_ID` bigint(20) NOT NULL,
  `EVENT_DATE` date DEFAULT NULL,
  `title` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`EVENT_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Hibernate在启动时则会执行update语句。

alter table hibernate4.EVENT 
       add column version integer

总结

create, create-drop选项要谨慎使用,因为其会执行删表语句。
validate 一般适用于线上环境,用于校验实体与数据库中的字段是否对应
update 一般用于本地快速开发,定义好实体后,Hibernate会自动创建和更新表,省去了手动更新数据库表的麻烦。

 类似资料: