【问题标题】:Duplicate key value violates unique constraint "hibernate_sequences_pkey" exception by Postgres重复的键值违反 Postgres 的唯一约束“hibernate_sequences_pkey”异常
【发布时间】:2018-05-20 20:20:47
【问题描述】:

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

id的策略定义如下:

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

我知道这种策略对于 Postgres 来说并不是完美的解决方案,但是它是上述异常的原因吗?

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

【问题讨论】:

    标签: postgresql hibernate jpa spring-data


    【解决方案1】:

    经过一些测试,问题似乎确实是由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;
    } 
    

    【讨论】:

      【解决方案2】:

      在从 Hibernate 4 迁移到 5.3.1(Wildfly 14.0.1)时,我也遇到了与“duplicate key value违反了唯一约束“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 参数设置为真值(因为它默认为假值,在这种情况下,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 属性设置为 false 值(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

      【讨论】:

        猜你喜欢
        • 2020-05-28
        • 2022-11-04
        • 2012-06-20
        • 2012-03-03
        • 2019-03-20
        • 2021-04-10
        • 2020-04-08
        • 1970-01-01
        相关资源
        最近更新 更多