Problem Overview
At seemingly random times, we get the exception "postgresql duplicate key violates a unique constraint." I really think I know what our problem is, "but I donโt want to make changes to the code without having a reproducible test case. But since we couldnโt play it in any environments other than random in production, I ask for help from SO.
In this project, we have several postgres databases and a primary key sequence configured for each table in each database. These sequences are created as follows:
create sequence PERSONS_SEQ; create sequence VISITS_SEQ; etc...
We use these sequences to create primary keys for objects such as this:
@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
I think that I recognize 2 problems with this configuration:
1) Both @SequenceGenerators indicate the same name attribute, even if they should be displayed in different database sequences.
2) The distribution attribute @SequenceGenerator allocS is 50 by default (we use hibernate as the JPA provider), so I think the create sequence syntax should indicate to what extent the sequence should increase, in particular, by 50 to match the distribution.
Based on this assumption, I think the code should be modified something like this:
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; ... }
I would just experience this, and not ask a question about SO, but again, we could not reproduce this production problem in any other environments. And even in production, a unique violation of restrictions occurs only at seemingly random times.
Questions:
1) Am I correct in my analysis of what changes were supposed to correct this unique violation of restrictions?
2) What are the best practices for using sequence generators when using hibernate as a JPA provider?