Hibernate, @SequenceGenerator and allocationSize
我们都知道使用
这是错误的行为,并与说明以下内容的规范冲突:
allocationSize - (Optional) The amount to increment by when allocating sequence numbers from the sequence.
需要说明的是:我不担心生成的ID之间的差距。
我关心与基础数据库序列不一致的ID。例如:任何其他应用程序(例如,使用纯JDBC)可能要在从序列获得的ID下插入新行-但所有这些值可能已被Hibernate使用!疯狂。
有人知道解决此问题的任何方法(不设置
编辑:
弄清楚。
如果最后插入的记录的ID =
另一方面:规范说(据我所知),数据库序列应已设置为
更新:
如下所述,史蒂夫·埃伯索尔(Steve Ebersole):可以通过设置
谢谢大家。
更新2:
对于将来的读者,您可以在下面找到一个有效的示例。
1 2 3 4 5 6 7 8 9 |
persistence.xml
1 2 3 4 5 | <persistence-unit name="testPU"> <properties> <property name="hibernate.id.new_generator_mappings" value="true" /> </properties> </persistence-unit> |
绝对清楚...您所描述的内容与规范没有任何冲突。规范讨论的是Hibernate分配给您的实体的值,而不是实际存储在数据库序列中的值。
但是,可以选择要获取的行为。首先看到我的答复:是否有一种方法可以使用JPA批注和Hibernate动态选择@GeneratedValue策略?这将为您提供基础知识。只要您设置为使用那个SequenceStyleGenerator,Hibernate就会使用SequenceStyleGenerator中的"池优化器"来解释
序列ID的下一代基于分配大小。
通过默认,它被保留为
因此,在使用
我在Hibernate 5中也遇到了这个问题:
1 2 3 4 | @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = SEQUENCE) @SequenceGenerator(name = SEQUENCE, sequenceName = SEQUENCE) private Long titId; |
收到如下警告:
Found use of deprecated [org.hibernate.id.SequenceHiLoGenerator] sequence-based id generator; use org.hibernate.id.enhanced.SequenceStyleGenerator instead. See Hibernate Domain Model Mapping Guide for details.
然后将我的代码更改为SequenceStyleGenerator:
1 2 3 4 5 6 7 | @Id @GenericGenerator(name="cmrSeq", strategy ="org.hibernate.id.enhanced.SequenceStyleGenerator", parameters = { @Parameter(name ="sequence_name", value ="SEQUENCE")} ) @GeneratedValue(generator ="sequence_name") private Long titId; |
这解决了我的两个问题:
深入研究休眠源代码和
在50次插入之后,下面的配置转到Oracle db获取下一个值。 因此,每次调用时,使INST_PK_SEQ递增50。
Hibernate 5用于以下策略
也在下面检查
http://docs.jboss.org/hibernate/orm/5.1/userguide/html_single/Hibernate_User_Guide.html#identifiers-generators-sequence
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | @Id @Column(name ="ID") @GenericGenerator(name ="INST_PK_SEQ", strategy ="org.hibernate.id.enhanced.SequenceStyleGenerator", parameters = { @org.hibernate.annotations.Parameter( name ="optimizer", value ="pooled-lo"), @org.hibernate.annotations.Parameter( name ="initial_value", value ="1"), @org.hibernate.annotations.Parameter( name ="increment_size", value ="50"), @org.hibernate.annotations.Parameter( name = SequenceStyleGenerator.SEQUENCE_PARAM, value ="INST_PK_SEQ"), } ) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator ="INST_PK_SEQ") private Long id; |
史蒂夫·埃伯索尔(Steve Ebersole)和其他成员,
您能否解释一下ID差距较大(默认值为50)的原因?
我正在使用Hibernate 4.2.15,并在org.hibernate.id.enhanced.OptimizerFactory cass中找到以下代码。
1 2 3 4 5 6 | if ( lo > maxLo ) { lastSourceValue = callback.getNextValue(); lo = lastSourceValue.eq( 0 ) ? 1 : 0; hi = lastSourceValue.copy().multiplyBy( maxLo+1 ); } value = hi.copy().add( lo++ ); |
每当它到达if语句的内部时,hi值就会变得更大。因此,在频繁重启服务器的测试过程中,我的ID会生成以下序列ID:
1,2,3,4,19,250,251,252,400,550,750,751,752,850,1100,1150。
我知道您已经说过它与规范没有冲突,但是我相信对于大多数开发人员来说这将是非常出乎意料的情况。
任何人的意见都会很有帮助。
吉万
更新:
ne1410s:感谢您的编辑。
cfrick:好的。我去做。这是我在这里的第一篇文章,不确定如何使用。
现在,我更好地理解了为什么将maxLo用于两个目的:由于休眠一次调用数据库序列,在Java级别中不断增加id并将其保存到DB中,因此Java级别的id值应考虑不调用而更改了多少DB序列下次调用该序列时。
例如,序列ID在某个点为1,然后休眠输入5、6、7、8、9(分配大小= 5)。下次,当我们得到下一个序列号时,DB返回2,但是休眠状态需要使用10、11、12 ...因此,这就是为什么" hi = lastSourceValue.copy()。multiplyBy(maxLo + 1)"是用于从数据库序列返回的2中获取下一个ID 10。似乎只有麻烦的事情是频繁的服务器重启期间,这是我的问题所在,而且间隔更大。
因此,当我们使用SEQUENCE ID时,表中插入的ID将与DB中的SEQUENCE号不匹配。
我将在DDL中检查模式中的序列。 JPA实施仅负责创建具有正确分配大小的序列。因此,如果分配大小为50,则您的序列的DDL中的增量必须为50。
这种情况通常可能发生在创建分配大小为1的序列,然后将其配置为分配大小为50(或默认值)但不更新序列DDL的情况下。