为啥eclipselink每次重新启动时都会消耗整个allocationSize?

Posted

技术标签:

【中文标题】为啥eclipselink每次重新启动时都会消耗整个allocationSize?【英文标题】:Why does eclipselink consume the whole allocationSize each time it's rebooted?为什么eclipselink每次重新启动时都会消耗整个allocationSize? 【发布时间】:2010-10-27 20:57:16 【问题描述】:

我刚刚注意到,对于我的实体的 id,eclipselink 分配了一个 id 1 + 之前在同一会话中分配的大号 (1),而不是在元素表 (2) 中。这违背了我对应用程序的期望。

告诉它执行 2 的最简单方法是什么?

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int objId;

这是我在数据库中的内容:

ij> connect 'jdbc:derby:db';
ij> set schema memo;
0 Zeilen eingef?gt/aktualisiert/gel?scht
ij> select * from meaning;
OBJID      |LASTPUBLI&|USR_EMAIL                                                                                                                       
-------------------------------------------------------------------------------------------------------------------------------------------------------
1          |NULL      |NULL                                                                                                                            
2          |2010-10-27|NULL                                                                                                                            
51         |NULL      |NULL                                                                                                                            
101        |NULL      |NULL                                                                                      

【问题讨论】:

【参考方案1】:

在 Derby 中使用 GenerationType.AUTO 策略时,EclipseLink 默认使用 表生成器 策略。

然后,当需要生成Id时,EL会根据allocationSize(默认为50)预先分配id。为此,它将首先更新存储生成的最后一个值的列,以将其递增allocationSize

UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?
    bind => [50, SEQ_GEN]

然后会读取新的值:

SELECT SEQ_COUNT FROM SEQUENCE WHERE SEQ_NAME = ?
    bind => [SEQ_GEN]

完成后,EL 使用当前的 value 预分配一个 id 池 - allocationSize + 1 作为“first”,value 作为“last”:

local sequencing preallocation for SEQ_GEN: objects: 50 , first: 1, last: 50

并且会从内存中提供 ids 直到达到最后一个值并重新开始一个循环。

现在,如果您重新启动 JVM,对于 EL 来说,除了预先分配一个新的 id 池之外,没有其他安全的方法,“丢失”那些“先前”范围内尚未使用的 ID(想想多 JVM 等) ),这解释了您的示例中从 2 到 51 的“跳跃”。

如果您想避免这种情况,我的建议是切换到 Derby 支持的 IDENTITY 策略(我不认为将表生成器配置为使用 1 的 allocationSize 会很好想法)。


我认为将表生成器配置为使用 1 的 allocationSize 不是一个好主意。为什么不?

如果您必须从每个插入的“序列”表中读取,则会影响性能。但另一方面,1)在您的情况下,这可能不是问题 2)这是唯一允许获得真正顺序 ID 的策略。

如果您有兴趣,您应该能够使用 XML 描述符中的 table-generator 元素全局配置它。

EL 强烈反对身份策略,此外似乎还有地雷(因为在读取值之前您必须等待提交,我可能在某处做某事)。

好吧,我无法确认 EL(我现在不会测试),但是当您使用 IDENTITY 策略时,Hibernate 会立即对 persist 执行插入操作。我认为 EL 会以同样的方式行事。但我可能错了,这似乎不是规范要求的。

参考文献

JPA 维基书 Sequence Strategies Advanced Sequencing Sequence Strategies

【讨论】:

我认为将表生成器配置为使用 1 的 allocationSize 不是一个好主意。为什么不? EL 非常不鼓励身份策略,此外似乎还有地雷(因为您必须等待提交才能读取值,我可能在某处做某事)。

以上是关于为啥eclipselink每次重新启动时都会消耗整个allocationSize?的主要内容,如果未能解决你的问题,请参考以下文章

每次重新启动时都会重置 MAMP 配置设置

Heroku:每次测功机重新启动时都会丢失 Django 数据库文件

与本机应用程序集成时,React-native 应用程序在每次导航时都会重新启动

为啥每次选择另一个 TextField 时都会调用 KeyboardWillShowNotification?

为啥ajax调用在每次调用时都会输入成功和错误块?

Angular2,为啥每次移动鼠标时都会调用函数