JPA 2 @SequenceGenerator @GeneratedValue产生唯一约束违规

问题概述

在看似随机的时间我们得到一个例外“postgresql重复键违反了唯一约束”。 我确实认为我知道我们的问题是什么,但我不想在没有可重复的测试用例的情况下对代码进行更改。 但由于我们无法在生产中随机以外的任何环境中重现它,我正在寻求SO的帮助。

在这个项目中,我们有多个postgres数据库,以及为每个数据库中的每个表配置的主键序列。 这些序列是这样创建的:

create sequence PERSONS_SEQ; create sequence VISITS_SEQ; etc... 

我们使用这些序列为实体生成主键,如下所示:

 @Entity @Table(name = "visits") public class Visit { @Id @Column(name = "id") @SequenceGenerator(name = "seq", sequenceName = "visits_seq") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq") private int id; ... } @Entity @Table(name = "person") public class Person { @Id @Column(name = "id") @SequenceGenerator(name = "seq", sequenceName = "persons_seq") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq") private int id; ... } 

分析

我想我认识到这个配置有两个问题:

1)@SequenceGenerators都指定相同的名称属性,即使它们应该映射到不同的数据库序列。

2)@SequenceGenerator的allocationSize属性默认为50(我们使用hibernate作为JPA提供者)所以我认为创建序列语法应该指定序列应该增加多少,特别是50以匹配allocationSize。

根据这个猜测,我认为代码应该修改为这样的:

 create sequence PERSONS_SEQ increment by 50; create sequence VISITS_SEQ increment by 50; etc... @Entity @Table(name = "visits") public class Visit { @Id @Column(name = "id") @SequenceGenerator(name = "visits_seq", sequenceName = "visits_seq") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "visits_seq") private int id; ... } @Entity @Table(name = "person") public class Person { @Id @Column(name = "id") @SequenceGenerator(name = "persons_seq", sequenceName = "persons_seq") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "persons_seq") private int id; ... } 

我只是测试这个,而不是在SO上询问问题,但同样,我们还没有能够在任何其他环境中重现这个生产问题。 甚至在生产中,唯一约束违规仅发生在看似随机的时间。

问题:

1)在分析修复此唯一约束违规的更改时,我是否正确?

2)将hibernate用作JPA提供程序时,使用序列生成器的最佳实践是什么?

  1. 是的,您的分析是正确的。 您正确识别了问题(我们遇到了类似的问题)。 并且……如果你要把它投入生产,不要忘记:

    • 或者使用正确的初始值/初始ID手动生成新序列生成器的序列表(否则hibernate将从1开始,您将再次获得)
    • 或者在Code中设置该值(在@SequenceGenerator检查initalValue )。
  2. 我无法列举最佳实践,但我想你可以降低50的限制。另外我没有PostgreSQL的经验,但在MySQL中你有一个简单的seq表。 生成器和hibernate使整个东西。

我也有类似的问题。 就我而言,我直接通过SQL导入数据。 这导致了’hibernate_sequence’的问题。 hibernate_sequence是id 123,但我的表中有一行id大于123。