【问题标题】:JBoss EAP 6.x with Hibernate Oracle Sequence Duplicate Value on Primary KeyJBoss EAP 6.x 与 Hibernate Oracle Sequence Duplicate Value on Primary Key
【发布时间】:2013-07-23 10:34:27
【问题描述】:

我已经使用纯 JPA 注释定义了许多 Hibernate 实体。它们在我的数据库上使用预定义的 Oracle 序列来自动生成主键值。

@Id
@SequenceGenerator(name = "USERS_ID_GENERATOR", sequenceName = "MY_SEQ")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USERS_ID_GENERATOR")
@Column(name = "U_ID", updatable = false, unique = true, nullable = false, precision = 19)
private Long id;

当它被部署到 JBoss EAP 6.1 时,最初一切正常,但是在短时间内 Hibernate 开始在插入时生成重复键(ORA-00001 错误)。

我不关心 id 顺序或间隙,但不能容忍重复的键...这是怎么回事?

【问题讨论】:

    标签: oracle hibernate jpa wildfly sequence


    【解决方案1】:

    这没有很好的记录,这里和其他站点上的许多解决方案都与 HiLo 序列生成器是默认值的旧版本的休眠有关。但是经过调查我发现根本原因是JBoss EAP 6 集

    hibernate.id.new_generator_mappings=true 
    

    默认情况下,它使用 org.org.hibernate.id.enhanced.SequenceStyleGenerator 而不是旧版本。

    Hibernate SequenceStyleGenerator 默认增量为 1(检查代码!),但是 JPA 将此生成器中的增量值覆盖为 50。这意味着生成器查看序列 nextval 并保留 50 个 id 的缓存以供使用,开始从 nextval - 49。当这些用完时,生成器从 oracle 读取下一个序列,并重复该过程。因此,一旦第一系列 id 用完,我们就会开始看到重复的键。

    所以分辨率是:

    1) 使用增量值 50 定义您的 Oracle 序列以匹配 JPA 默认值

    CREATE SEQUENCE MY_SEQ
    START WITH 50
    MAXVALUE 9999999999999999999
    INCREMENT BY 50
    NOCYCLE;
    

    2) 将 allocationSize=1 添加到 @SequenceGenerator 注释 - 这会强制 SequenceGenerator 返回从 oracle 序列中读取它所需的每个 ID 的下一个值(具有潜在的性能影响)

     @SequenceGenerator(name = "USERS_ID_GENERATOR", sequenceName = "MY_SEQ", allocationSize = 1)
    

    ,或

    3) 定义 Oracle 序列 INCREMENT BY 某个其他值,并确保 allocationSize 匹配。

    回答了我自己的问题,希望能帮助解决这个问题的其他人。

    【讨论】:

    • 虽然我正在搜索一些其他信息,但您添加信息作为帮助他人的答案的方式值得 +1。
    【解决方案2】:

    你的答案是正确的;只是一些更多的细节。

    有些帖子建议关闭 hibernate.id.new_generator_mappings=false。

    但是根据 https://docs.jboss.org/author/display/AS71/JPA+Reference+Guide#JPAReferenceGuide-Persistenceunitproperties

    两者之间有区别 GenerationType.AUTO 和 GenerationType.SEQUENCE

    如果您选择自动,您将选择休眠本机。 如果您选择 SEQUENCE,您将匹配 hilo 算法进行序列分配,这与 SequenceStyleGenerator 绝对不同。 如果您切换 hibernate.id.new_generator_mappings=true / false,这将不兼容。

    所以答案 1) 绝对是正确的 / 遵循当前的 Hibernate/Jboss 建议。

    ...并且为所有实体设置 allocationSize=1 的答案不是一个好的解决方案。 看 http://itdevworld.wordpress.com/2009/12/20/hibernate-sequencegenerator-with-allocationsize1-leads-to-huge-contention/

    【讨论】:

    • 谢谢@skay,我已经添加了一个澄清来回答2)关于单个分配的潜在性能影响。如果序列是使用“顺序”设置的,这在 RAC 环境中可能尤其明显。
    • 注意 - 链接中的 JBoss 文档提到这是一个 Hibernate 4.x 设置。 Hibernate 3 也支持它。在我们的应用程序中与 3.6.0.Final 一起使用它。JBoss AS 7 附带 4.x,因此他们的文档如何引用它。
    猜你喜欢
    • 2018-12-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-23
    • 2011-10-22
    • 2010-10-07
    • 2021-03-02
    • 2021-03-13
    • 2018-05-22
    相关资源
    最近更新 更多