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

4
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

第一个“获取的序列值”是正确的,22643确实来自MY_SEQ.nextVal。但是随后使用的“生成的标识符”是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和Oracle序列不使用它可能是相关的,但是那个问题涉及缺口,而我获得的ID比获取的序列值
PS:其他问题讨论了优化效率的序列生成器策略。这些数据的单个记录每月只插入一次,而且只能从此类中插入。因此,在这里效率不是一个问题。

更新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
1个回答

6
正如我在第三个更新中提到的那样,JPA从序列中“获取50个id”,并在内存中计算它们以提高效率。
这种行为由javax.persistence.SequenceGenerator.allocationSize指定,默认值为50。
“(可选)从序列分配序列号时要增加的数量。”
对我来说,这一点根本不直观,或其他人,因为我的Oracle数据库序列应该定义这种行为,而50在那里不是标准默认值。
快速而简单的解决方案是指定allocationSize=1:
@SequenceGenerator(name = "generator", sequenceName = "MY_SEQ",
                   allocationSize = 1)

现在,每次插入时 Oracle 序列会自动递增。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接