問題概述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;
...
}
分析
我覺得我認識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;
...
}
我只想測試這個,而不是要求對這樣的問題,但同樣,我們一直沒能在任何其他環境中重現此生產問題。即使在生產中,唯一的約束違規也只發生在看似隨機的時間。
問題:
1)我是在我的改變應該是解決這一問題的唯一約束違規問題分析是正確的?
2)使用hibernate作爲JPA提供程序時使用序列生成器的最佳做法是什麼?