问题概述
在看似随机的时间,我们得到一个异常“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;
...
}
分析
我想我认识到此配置存在 2 个问题:
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提供者时,使用序列生成器的最佳实践是什么?