【发布时间】:2025-12-30 12:35:07
【问题描述】:
默认的@GeneratedValue策略用于spring boot 1.5 web app,没有任何类型的重复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());
... 用于生成一个新的Car,ID 为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(但这只是把罐子踢下去,并不是真正的解决方案:最终序列会赶上并破坏事物)
- 编写我自己的序列生成器(但必须有更简单的方法来初始化数据库!)
- 使用旧的序列生成(但同样,如果这样做没有优势,他们为什么要更改它?hibernate 开发人员肯定有一些更好的初始化方法!)。
- 以某种方式为新 ID 指定一个起始值(如何以故障安全的方式执行此操作?是否有一个属性可以进入我的
application.properties以保持集中?)
我想在 spring-boot web 应用程序的上下文中使用它,并使其尽可能简单并接近最佳实践。有什么建议吗?
【问题讨论】:
-
您好,我不确定您的问题是否正确,但我遇到了类似的问题,错误是我通过 SQl 语句插入了一个元素。在此语句中,ID 设置为固定值,但据我所知,您的 GeneratedValue 由 Spring 管理,它无法识别手动设置的 ID。因此,当您使用 Spring 上下文插入元素时,GeneratedValue 序列将从 1 开始并引发错误,因为 ID 已经存在。
-
@MatthiasLauber 是的,这就是问题所在。但是,我需要能够插入 SQL 语句,因为否则我不能包含关系(需要 ID 来匹配外键值)。否则,您将如何使用 ID 初始化数据库?另一种初始化 ID 的方法是有效的答案。
-
您使用 Flyway 吗?在那里你为你的表编写一个 SQL 模式。您可以定义一个序列并告诉您的表使用序列的 nex 值生成 ID 并将序列插入您的 Spring 实体中
-
@MatthiasLauber 我没有使用 Flyway,并希望最大限度地减少依赖关系。但是,这似乎是一个可行的解决方案:谢谢。
标签: spring hibernate spring-boot jpa