java Hibernate在使用序列时生成负id值

qaxu7uf2  于 2023-01-24  发布在  Java
关注(0)|答案(5)|浏览(183)

我有一个定义如下的类:

@Id
@SequenceGenerator(name = "SEQ_ACE_WORKERS_QUEUE_STATS_ID", sequenceName = "SEQ_ACE_WORKERS_QUEUE_STATS_ID", allocationSize = 500)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_ACE_WORKERS_QUEUE_STATS_ID")
@Column(name = "ID")
private long Id;

当我们在Jboss 4.2.3上运行它时,它运行良好,并生成了正确的ID(从1000+开始)
现在我们转到jboss 7.1.1,它会生成负ID!(从-498开始,然后向上)
知道为什么会这样吗?

deikduxw

deikduxw1#

新行为如下:

  • AllocationSize* 是为Hibernate保留的主键值范围。只有在Hibernate使用了此范围的主键后,才会从dual中选择seq.nextval

因此,您必须allocationSize(Hibernate)和序列increment by(DB)上声明相同的值
显式设置allocationSize=500时,例如在Oracle上

create sequence SEQ_ACE_WORKERS_QUEUE_STATS_ID
       MINVALUE 1 
       MAXVALUE 999999999999999999999999999 
       START WITH 1
       INCREMENT BY 500 
       NOCACHE 
       NOCYCLE;

否则,您将注意到由于主键冲突而从DB中引发的负值或约束错误。
当应用服务器重新启动时,您会注意到最近分配的主键和重新启动时选择的“新”序列号之间的“跳转”。
最终意见:因此,如果您不在Hibernate端指定allocationSize,您必须在DB端声明increment by 50。

qnakjoqk

qnakjoqk2#

我刚刚在从JBoss 6.1迁移到JBoss 7.1时遇到了这个问题。
根据JBoss AS 7.1 JPA文档(https://docs.jboss.org/author/display/AS71/JPA+参考+指南#JPA参考指南-持久性单元属性),
JBoss 7.1会自动设置多个休眠属性。其中一个要设置的属性是hibernate.id.new_generator_mappings,它会激活使用不同算法且不向后兼容的新ID生成器。在persistence.xml文件中将此属性设置为false将恢复旧的ID生成器行为。
hib4文档还包含有关新ID生成器的信息:www.example.com网站。http://docs.jboss.org/hibernate/core/4.0/manual/en-US/html_single/#mapping-declaration-id-generator.
hib文档明确指出,默认情况下不启用新的ID生成器,但是如上所述,JBoss 7.1会自动启用它们。

hc2pp10m

hc2pp10m3#

在我的persistence.xml中将hibernate.id.new_generator_mappings设置为false只是解决我的问题的第一部分:
为了完全解决这个问题,我在@SequenceGenerator中添加了allocationSize1(我省略了)。

bvjveswy

bvjveswy4#

我们遇到了一个类似的错误,但原因(可能)不同:
我们没有显式定义allocationSize(因此使用默认值50)。我们运行了应用程序,但删除了数据库并重新创建了它。Hibernate使用了它的id缓存,然后与数据库通信以获得新的id。
现在hibernate-id缓存至少是50(对于某些表可能要高得多),但是数据库被删除,重建,现在是空的,所以已经有一些不一致了...但是不管什么原因hib在-48开始了下一轮的id。
我们遇到了一个后续错误,因为我们的实体的ID定义为数据类型int而不是Integer,当hib继续计数并到达0的实体时,它认为它还没有在数据库中,试图创建INSERT而不是UPDATE,并得到了一个密钥验证错误。
我仍然不能解释为什么hib在遇到这种不一致的情况下决定从-48开始键...但是对于我们来说,在改变数据库中的序列之前,简单地关闭应用程序就可以解决这个错误。而且我们所有的实体现在都使用Integer代替int作为id。
希望这些信息对外面的人有帮助。

jfgube3f

jfgube3f5#

谢谢!!!添加下面的代码后工作正常

allocationSize = 1

相关问题