在Spring-boot 2中数据库初始化后避免重复的主键

时间:2019-03-01 11:43:18

标签: spring hibernate spring-boot jpa

用于Spring Boot 1.5 Web应用程序的默认@GeneratedValue策略,没有任何类型的重复ID冲突

...使用一个简单的实体(例如该实体)

// in my/package/Car.java
// ...
@Entity
public class Car {
    private long id;
    private String company;
    private String model;

    @Id
    @GeneratedValue
    public long getId() {
        return id;
    }

    // ... more getters and setters
}

...并在启动时使用

初始化数据库
# in src/main/resources/import.sql
insert into car values (1, 'Tesla', 'Roadster');

...然后再插入另一辆车

Car c = new Car();
c.setCompany("Ford");
c.setModel("Pinto");
entityManager.persist(c);
entityManager.flush();

// expect no issue inserting, and a valid ID
log.info("Assigned ID is " + c.getId());

...用于生成ID为Car的新2。只要没有冲突,我就不会真正在乎生成的ID。但是,此相同的代码现在会引发以下异常:

org.hsqldb.HsqlException: integrity constraint violation: unique constraint or index violation; SYS_PK_10095 table: CAR (数据库是HSQL,我宁愿不必替换它)

...,因为default sequence generation in hibernate 5.2现在不考虑现有的插入内容。

我仍然可以通过import.sql初始化数据库的可能解决方法是什么?我知道我可以

  • 在初始化时使用非常大的id(但这只是为了解决问题,并不是一个真正的解决方案:最终,该序列将追赶并破坏事物)
  • 编写自己的序列生成器(但必须有一种更简单的初始化数据库的方法!)
  • 使用旧的序列生成器(但是同样,为什么这样做没有优势,为什么他们要更改它?休眠的开发人员肯定有一些更好的方法来初始化事情!)
  • 以某种方式为新ID指定一个起始值(我该如何以故障安全的方式执行此操作?我可以在application.properties中使用某个属性来使其保持集中状态吗?)

我想在Spring-boot Web应用程序的上下文中使用它,并使其保持简单并尽可能接近最佳实践。有建议吗?

1 个答案:

答案 0 :(得分:2)

从版本5开始,使用SEQUENCE代替IDENTITY进行id生成。 Migration from Hibernate 4 to 5

发生了什么事?

您使用脚本插入了ID为1的记录。序列保持为1。它想插入1导致唯一的PK违反。

解决方案

不要使用自动生成类型。使用身份。然后按脚本插入记录,IDENTITY将自动增加。另外,您不需要插入ID值:

 DECLARE temp_id INTEGER;
 INSERT INTO CUSTOMERS VALUES (DEFAULT, firstname, lastname, CURRENT_TIMESTAMP);
 SET temp_id = IDENTITY();
 INSERT INTO ADDRESSES VALUES (DEFAULT, temp_id, address);