JBoss EAP 6.x 与 Hibernate Oracle Sequence Duplicate Value on Primary Key

Posted

技术标签:

【中文标题】JBoss EAP 6.x 与 Hibernate Oracle Sequence Duplicate Value on Primary Key【英文标题】:JBoss EAP 6.x with 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 顺序或间隙,但不能容忍重复的键...这是怎么回事?

【问题讨论】:

【参考方案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,因此他们的文档如何引用它。

以上是关于JBoss EAP 6.x 与 Hibernate Oracle Sequence Duplicate Value on Primary Key的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 JBoss7.1.EAP 中运行应用程序时出现 java.lang.NoSuchMethodError

jboss eap-6.1 无法处理部署“education.war”的阶段 POST_MODULE

JBOSS EAP实战-集群NGINX集成队列与安全

JBoss AS 与 WildFly 8

MQJCA1011:无法分配与 JBOSS EAP 6.2.0 的 JMS 连接

不能使用jconsole连接到JBoss eap7.1