【问题标题】:Liquibase + Postgresql + Spring Jpa : Id auto increment issueLiquibase + Postgresql + Spring Jpa:Id 自动递增问题
【发布时间】:2017-11-28 09:17:49
【问题描述】:

我在实体中有以下Id描述:

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

生成此 id 的 Liquibase 指令如下:

  <column name="id" autoIncrement="true"  type="INT">
     <constraints nullable="false" primaryKey="true" primaryKeyName="pk_entity"/>
  </column>

我还有 liquibase 脚本可以插入到这个表中的预定义值,例如

    <insert tableName="entityTable" schemaName="public">
        <column name="id">1</column>    
        <!- other fields-->
    </insert>

当我尝试使用 Jpa 存储库插入没有 id 的新记录时,问题出现了。 我收到一条错误消息,例如“重复 ID”。 所以,我知道 jpa(hibernate) 不使用 postgresql 序列来获取新的 id 值。而且我不想在实体的 id 描述中包含序列名称。我希望这种情况可以由 postgresql 本身解决。 而且我不会使用“hibernate_sequence”。 所以,知道如何解决这个问题。 谢谢。

【问题讨论】:

  • FYI JPA GenerationType.IDENTITY 用于 PostgreSQL 将意味着使用“SERIAL”列类型(即在数据存储中生成)。这不是一个序列。如果你想要一个 SEQUENCE 那么你会使用 JPA GenerationType.SEQUENCE
  • 我知道,但 liquibase 不会生成“串行”类型。
  • 所以如果你想同时使用 JPA 和 Liquibase 就不能使用 IDENTITY 和 JPA ...
  • 如果您使用autoIncrement="true",那么 Liquibase 生成一个serial

标签: java postgresql hibernate jpa liquibase


【解决方案1】:

Liquibase 的指令 autoIncrement="true" 为 PostgreSQL 生成 serial 列。对于serial 列,PostgreSQL 将创建一个名称类似于tablename_colname_seq 的序列。将从该序列中分配默认列值。

但是当你显式在序列列中插入一个值时,它不会影响序列生成器,它的下一个值也不会改变。所以它可以生成一个重复的值,这正是你的情况。

为防止在插入显式值后发生这种情况,您需要使用 ALTER SEQUENCE 语句或 setval() 函数更改序列生成器的当前值,例如:

ALTER SEQUENCE tablename_colname_seq RESTART WITH 42;

SELECT setval('tablename_colname_seq', (SELECT max(colname) FROM tablename));

这应该可以解决问题。

【讨论】:

  • 我认为在多线程应用程序中手动更新序列不是一个好主意。
【解决方案2】:

首先创建到表名示例:

CREATE TABLE TABLE_NAME(ID_NAME SERIAL PRIMARY KEY NOT NULL);

然后在您的注释中:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-22
    • 2011-09-17
    • 1970-01-01
    • 2017-06-22
    • 2019-07-23
    • 2014-10-30
    相关资源
    最近更新 更多