休眠序列nextVal已解决但未使用(Oracle) [英] Hibernate sequence nextVal resolved but not used (Oracle)

查看:89
本文介绍了休眠序列nextVal已解决但未使用(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

第一个获得的序列值"是正确的,如MY_SEQ.nextVal所示,正确的是22643.但是,然后使用的生成的标识符"是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上下文配置.我在那里看不到任何明显相关的东西.

使用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

解决方案

正如我在第3次更新中提到的那样,JPA正在从序列中提取50个id",并在内存中对它们进行计数以提高效率.

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

(可选)从序列中分配序列号时要增加的数量.

这对我来说不是很直观,或其他,因为我是Oracle数据库应该使用序列来定义此行为,并且50不是此处的标准默认值.

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

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

现在,每个插入的O​​racle序列都会递增.

Hibernate is not assigning objects ids from the Oracle sequence as expected. Here's what I see in the Hibernate debug logs.

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

The first "sequence value obtained" is correct, 22643 comes right from MY_SEQ.nextVal as it says. But then the "generated identifier" that gets used is 22594. What gives?

I've tried tweaking the generator strategy to no avail.

@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;

I can include my Spring Hibernate context configuration if that'll help. I don't see anything in there that looks obviously relevant.

Hibernate with Oracle sequence doesn't use it is very probably related, but that deals with gaps while the id I get is less than the sequence value obtained.

PS: Other tickets discuss sequence generator strategies that optimize efficiency. A single record of this data is inserted once a month or so, and only from this class. So, efficiency isn't a concern here.

Update 1

I am able to recreate this in HSQLDB in Oracle emulation mode too. So it's surely a Hibernate issue.

Update 2

The offset is always exactly 49. The example above correctly fetched 22643 from the sequence, but then resolved 22594 as the next value.

22643-22594=49

In another example, the next sequence value was actually 4, and Hibernate gave me -45.

4-(-45)=49

Update 3

Subsequent inserts do not call the Oracle sequence's nextVal. I suspect JPA/Hibernate is trying to fetch ids in bulk upfront for efficiency.

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

解决方案

As I mentioned in my 3rd update, JPA was "fetching 50 ids" from the sequence up front and counting through them in memory for efficiency.

This behavior is specified by javax.persistence.SequenceGenerator.allocationSize which defaults to 50.

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

This isn't at all intuitive to me, or others, since my Oracle database sequence is supposed to define this behavior and 50 isn't a standard default there.

The quick and dirty solution was to specify allocationSize=1:

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

Now the Oracle sequence is incremented for every insert.

这篇关于休眠序列nextVal已解决但未使用(Oracle)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆