Hibernate 序列 nextVal 已解析但未使用 (Oracle)

Hibernate sequence nextVal resolved but not used (Oracle)

Hibernate 没有按预期从 Oracle 序列分配对象 ID。这是我在 Hibernate 调试日志中看到的内容。

DEBUG o.h.SQL:92 - select MY_SEQ.nextval from dual
DEBUG o.h.i.e.SequenceStructure:102 - Sequence value obtained: 22643
DEBUG o.h.r.j.i.ResourceRegistryStandardImpl:73 - HHH000387: ResultSet's statement was not registered
DEBUG o.h.e.i.AbstractSaveEventListener:118 - Generated identifier: 22594, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator

第一个"sequence value obtained"是正确的,22643正如它所说的那样来自MY_SEQ.nextVal。但是然后使用的 "generated identifier" 是 22594。什么给?

我尝试调整生成器策略但无济于事。

@Id
@SequenceGenerator(name = "generator", sequenceName = "MY_SEQ")
@GeneratedValue(generator = "generator", strategy = GenerationType.SEQUENCE)
@Column(name = "MY_ID", nullable = false, precision = 6, scale = 0)
private Integer id;

如果有帮助,我可以包括我的 Spring Hibernate 上下文配置。我在那里没有看到任何看起来明显相关的内容。

Hibernate with Oracle sequence doesn't use it 很可能是相关的,但是当我得到的 id 比获得的序列值 时处理间隙。

PS:其他工单讨论优化效率的序列生成器策略。此数据的单个记录大约每月插入一次,并且仅来自 class。所以,效率在这里不是问题。

更新 1

我也可以在 Oracle 仿真模式下在 HSQLDB 中重新创建它。所以这肯定是一个 Hibernate 问题。

更新 2

偏移量始终恰好为 49。上面的示例正确地从序列中提取了 22643,但随后将 22594 解析为下一个值。

22643-22594=49

另一个例子,下一个序列值实际上是4,而Hibernate给了我-45。

4-(-45)=49

更新 3

后续插入调用 Oracle 序列的 nextVal。我怀疑 JPA/Hibernate 正试图预先批量获取 ID 以提高效率。

DEBUG o.h.SQL:92 - select MY_SEQ.nextval from dual
DEBUG o.h.i.e.SequenceStructure:102 - Sequence value obtained: 22643
DEBUG o.h.r.j.i.ResourceRegistryStandardImpl:73 - HHH000387: ResultSet's statement was not registered
DEBUG o.h.e.i.AbstractSaveEventListener:118 - Generated identifier: 22594, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
...
DEBUG o.h.e.i.AbstractSaveEventListener:118 - Generated identifier: 22595, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator

正如我在第 3 次更新中提到的那样,JPA 是 "fetching 50 ids" 从前面的序列开始并在内存中计算它们以提高效率。

此行为由 javax.persistence.SequenceGenerator.allocationSize 指定,默认为 50。

(Optional) The amount to increment by when allocating sequence numbers from the sequence.

这对我来说一点都不直观,or others,因为我的 Oracle 数据库序列应该定义这种行为,而 50 不是那里的标准默认值。

快速而肮脏的解决方案是指定 allocationSize=1:

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

现在每次插入时 Oracle 序列都会递增。