重复的键值违反了Postgres的唯一约束“hibernate_sequences_pkey”异常

时间:2017-12-06 20:32:35

标签: postgresql hibernate jpa spring-data

基于My Spring Data(JPA / Hibernate)的应用程序在Postgres中持久化新实体时会增加负载以下异常: org.postgresql.util.PSQLException:错误:重复键值违反了唯一约束“hibernate_sequences_pkey”

id的策略定义如下:

@Id
@GeneratedValue(strategy = GenerationType.TABLE)
@Column(name = "ID")
public Long getId() {
    return id;
}

我知道这种策略不是Postgres的完美解决方案,但是上面例外的原因是什么?

使用Apache Camel路由生成负载,并且拆分器在多个线程上并行运行插入。

2 个答案:

答案 0 :(得分:3)

经过一些测试后,确实问题确实是由strategy = GenerationType.TABLE引起的。随着对strategy = GenerationType.SEQUENCE的更改,上面描述的问题已经消失了。

@Id
@SequenceGenerator(name = Consts.VEHICLE_ATTR_ID_SEQ,
        sequenceName = Consts.VEHICLE_ATTR_ID_SEQ,
        allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE,
        generator = Consts.VEHICLE_ATTR_ID_SEQ)
@Column(name = "ID", updatable = false)
public Long getId() {
    return id;
} 

答案 1 :(得分:0)

从Hibernate 4迁移到5.3.1(Wildfly 14.0.1)时,我还遇到了与“重复键值违反唯一约束” hibernate_sequences_pkey”错误消息有关的问题。在研究Hibernate 5.3.1的源代码后,我可以使用strategy = GenerationType.TABLE来消除错误(我也知道这种策略不是完美的解决方案)。主要问题在TableGenerator类中。要解决该问题,您还应该使用GenericGenerator批注例如:

@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = TableGenerator.DEF_TABLE)
@GenericGenerator(name = TableGenerator.DEF_TABLE, strategy
        = "org.hibernate.id.enhanced.TableGenerator", parameters = {
        @Parameter(name = TableGenerator.CONFIG_PREFER_SEGMENT_PER_ENTITY, value = "true")})
@Column(name="id")
private Integer id;

TableGenerator.CONFIG_PREFER_SEGMENT_PER_ENTITY参数设置为true值(因为默认情况下它具有false值,在这种情况下,Hibernate将在hibernate_sequences表中使用“默认”段名称而不是表名称)。 您还应该将hibernate.model.generator_name_as_sequence_name属性设置为false值,以仅具有一个hibernate_sequences表,否则,Hibernate将使用生成器名称作为序列表的名称(根据https://github.com/hibernate/hibernate-orm/commit/9a75fa8d979185b6014a814bf3ffd09e32143939#diff-936141a440957cd8a9c4a93a744e92a0的更改)。另外(但不是必需),您还可以将hibernate.id.generator.stored_last_used属性设置为假值(更改https://github.com/hibernate/hibernate-orm/commit/9af565510064635dba7e48087ab4e8f5ef439f0d),因为:

为了符合JPA规范,该值存储在 表中的Hibernate 5.3由 javax.persistence.TableGenerator是最后生成的值。 以前的Hibernate版本将下一个值存储为 使用。

为了向后兼容新设置, hibernate.id.generator.stored_last_used被介绍为 让您有机会回到旧的Hibernate行为。 迁移到5.3并使用@TableGenerator的现有应用程序具有 将hibernate.id.generator.stored_last_used设置为false