JPA 2 @SequenceGenerator @GenerateValue 产生唯一约束冲突

2023-11-26

问题概述

在看似随机的时候,我们会得到一个异常“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;
  ...
}

Analysis

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

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

2) @SequenceGenerator allocateSize 属性默认为 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 开始,您将再次得到)
    • 或在代码中设置该值(检查initalValue in @SequenceGenerator).
  2. 我无法列举最佳实践,但我想你可以将限制降低到 50。另外,我没有使用 PostgreSQL 的经验,但在 MySQL 中你有一个简单的 seq 表。生成器和休眠完成了所有的事情。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JPA 2 @SequenceGenerator @GenerateValue 产生唯一约束冲突 的相关文章

随机推荐