在 JPA 中使用 Flyway 创建的序列
Posted
技术标签:
【中文标题】在 JPA 中使用 Flyway 创建的序列【英文标题】:Use Sequence created by Flyway in JPA 【发布时间】:2019-04-02 09:36:39 【问题描述】:我正在使用 Spring Boot 2 / Flyway / Postgres 设置。
我想实现让Flyway创建一个带有序列的表,用于自动键迭代。 JPA 应该能够识别序列并使用它。
我让 Flyway 执行一个 PostgreSQL 脚本:
CREATE SEQUENCE config_id_seq;
CREATE TABLE config
(
ID BIGINT NOT NULL PRIMARY KEY DEFAULT nextval('config_id_seq'),
DESCRIPTION VARCHAR(500)
);
这是实体定义:
@Entity
@Table(name = "config")
public class Config
@Id
@SequenceGenerator(name = "config_id_sequence", sequenceName = "config_id_seq")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "config_id_sequence")
@Column(name = "id")
private long id;
@Column(name = "description")
private String description;
在启动时会抛出以下错误:
Caused by: org.postgresql.util.PSQLException: ERROR: relation "config_id_seq" already exists
Caused by: org.postgresql.util.PSQLException: ERROR: cannot change sequence "config_id_seq"
我的解释是 Flyway 成功执行了脚本并创建了一个序列。但是 JPA 想要在之后创建序列并失败,因为它已经存在。如果我在这里错了,请纠正我。
如果可能的话,现在如何配置 JPA 以重用现有序列?
【问题讨论】:
JPA 不使用列的“默认”规范。指定GeneratedValue
表示 JPA 使用一个序列,检索下一个值本身,然后在 INSERT 中使用它......不是您想要的(您希望从 INSERT 中省略该列,因此它使用默认规范...不可能)
@BillyFrost:如果我猜对了,我应该放弃 sequence 和 nextval() 命令并使用 JPA 来执行此操作?
是的。这就是 JPA 的价值生成所需要的。然后它创建序列,并管理对 nextval 的调用
@BillyFrost:很有趣。那么,连接到使用序列来增加 id 的现有数据库的 JPA 方式是什么?即使使用 ddl-auto: none?
作为第二个选项,您可以将生成策略设置为 IDENTITY,这意味着在数据库中设置字段值(用于 auto_increment / serial 类型)。这可能适用于您的情况。这样做虽然您将失去使用 JPA 进行批量插入的能力。
【参考方案1】:
我们需要将 spring.jpa.hibernate.ddl-auto 属性设置为 none 或者您可以跳过此属性,以便 spring 不会自行创建数据库对象。
如果我们使用flyway,那么我们应该只将创建数据库对象的责任交给flyway,即只使用flyway脚本创建所有数据库对象,例如表和序列。
指定 GeneratedValue 表示 JPA 使用序列,检索下一个值本身,然后在 INSERT 中使用它。
但请确保您的配置与您在实体类和 flyway 脚本中提到的配置相同。
【讨论】:
以上是关于在 JPA 中使用 Flyway 创建的序列的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot - Flyway - JPA 集成 - 创建名称为“flywayInitializer”的 bean 时出错 - information_schema 中的未知表“事件”