Java JPA 2@SequenceGenerator@GeneratedValue生成唯一约束冲突
问题概述 在看似随机的时候,我们会得到一个异常“postgresql重复键违反了唯一约束”。我想我知道我们的问题是什么,但我不想在没有可复制的测试用例的情况下对代码进行更改。但由于我们除了在生产中随机复制外,还无法在任何环境中复制它,所以我请求SO的帮助 在这个项目中,我们有多个postgres数据库,并且为每个数据库中的每个表配置了一个主键序列。这些序列是这样创建的:Java JPA 2@SequenceGenerator@GeneratedValue生成唯一约束冲突,java,hibernate,postgresql,jpa,Java,Hibernate,Postgresql,Jpa,问题概述 在看似随机的时候,我们会得到一个异常“postgresql重复键违反了唯一约束”。我想我知道我们的问题是什么,但我不想在没有可复制的测试用例的情况下对代码进行更改。但由于我们除了在生产中随机复制外,还无法在任何环境中复制它,所以我请求SO的帮助 在这个项目中,我们有多个postgres数据库,并且为每个数据库中的每个表配置了一个主键序列。这些序列是这样创建的: create sequence PERSONS_SEQ; create sequence VISITS_SEQ; etc...
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;
...
}
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;
...
}
我们使用这些序列为如下实体生成主键:
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;
...
}
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) 两个@SequenceGenerator都指定相同的name属性,即使它们应该映射到不同的数据库序列
2) @SequenceGenerator allocationSize属性默认为50(我们使用hibernate作为JPA提供程序),因此我认为创建序列语法应该指定序列应该增加多少,特别是增加50以匹配allocationSize
基于这一猜测,我认为应该将代码修改为如下内容:
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;
...
}
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提供者时,使用序列生成器的最佳实践是什么
- 手动为新序列生成器生成具有正确初始值/初始ID的序列表(否则hibernate将从1开始,您将再次获得)
- 或者在代码中设置该值(检查
@SequenceGenerator
中的initalValue
)
我有一个类似的问题。在我的例子中,我直接通过SQL导入数据。这导致“休眠_序列”出现问题。hibernate_序列的id为123,但我的表中有一些行的id大于123。也有同样的问题-由于某种原因,hibernate没有从序列中选择正确的编号。尝试了所有方法但没有成功,最终得出了以下解决方案:
@Entity
@Table(name = "events")
@SequenceGenerator(name = "events_id_seq", sequenceName = "events_id_seq", allocationSize = 1)
public class Event {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "events_id_seq")
private BigInteger id;
我必须将@SequenceGenerator放在类的顶部,而不是方法,分配大小也设置为1(如果您将此值保留为默认值,它将开始生成负ID)
spring数据jpa2.1.2
,hibernate5.3.7
,pg42.2.5
,我也遇到了同样的问题。我试着解决这个问题。也许这不是最好的解决办法,但我希望它能暂时解决你的问题
@SequenceGenerator(schema = "DS_TEST",name = "SEQ_PR_TEXT",sequenceName = "SEQ_PR_TEXT",
allocationSize = 1)
public class TextEntity {
@Id
@GeneratedValue(generator = SequenceConstant.SEQ_PR_TEXT,
strategy = GenerationType.SEQUENCE)
@Column(name = "PR_TEXT_ID")
private Long id;
}
这应该是一个注释,而不是一个答案。它在变量上对我有效。但是,
allocationsize=1
是帮助我的关键点。谢谢