如何调整EclipseLink的预分配策略

3
我正在处理一个项目,我们最近将持久性提供程序从OpenJPA更改为使用EclipseLink。这是一个庞大且古老的应用程序,在其中我们还从其他进程执行SQL插入,目前不可行迁移到JPA。
我们使用@TableGenerator引用一个表,该表跟踪要在插入中使用的ID。
当我们使用OpenJPA时,我们注意到它首先从表中选择下一个ID,然后更新表以预分配下一个ID。这正是旧SQL过程获取并预分配下一个ID的方式。
当我们切换到EclipseLink时,我们注意到相反的行为,它会先更新表以预分配下一个ID,然后开始执行插入操作。这导致我们遇到java.sql.SQLIntegrityConstraintViolationException异常,因为非JPA进程已经使用了最后一个预分配的ID来插入新记录,所以当JPA进程到达该ID时,数据库会报错,声称我们正在尝试使用已经使用的ID进行插入。
有没有办法告诉EclipseLink处理预分配与OpenJPA相同的方式?
以下是OpenJPA和EclipseLink的预分配策略示例,对于这些示例,我将allocationSize设置为5。
TEST  TRACE  [main] openjpa.jdbc.SQL - <t 22760146, conn 3658896> executing prepstmnt 9137209 SELECT NEXT_ID FROM ABC.table_ids WHERE TABLE_ID = ? FOR UPDATE [params=(String) 1034] [reused=0]
TEST  TRACE  [main] openjpa.jdbc.SQL - <t 22760146, conn 3658896> [94 ms] spent
TEST  TRACE  [main] openjpa.jdbc.SQL - <t 22760146, conn 3658896> executing prepstmnt 23999306 UPDATE ABC.table_ids SET NEXT_ID = ? WHERE TABLE_ID = ? AND NEXT_ID = ? [params=(long) 55, (String) 10, (long) 50] [reused=0]
TEST  TRACE  [main] openjpa.jdbc.SQL - <t 22760146, conn 3658896> [93 ms] spent

EclipseLink:

[EL Fine]: 2013-01-23 14:08:35.875--ClientSession(6215763)--Connection(10098848)--Thread(Thread[main,5,main])--UPDATE table_ids SET next_id = next_id + ? WHERE table_id = ?

        bind => [5, 10]

[EL Fine]: 2013-01-23 14:08:36.0--ClientSession(6215763)--Connection(10098848)--Thread(Thread[main,5,main])--SELECT next_id FROM table_ids WHERE table_id = ?

        bind => [10]

提前感谢您!

1个回答

1
问题不在于更新与选择的顺序,而在于是否有当前值的解释。EclipseLink假定它获取当前值,而OpenJPA似乎没有。理想情况下,您应该能够更改非JPA用法以做出相同的假设。如果无法,则可以在EclipseLink中编写自己的自定义Sequence对象。要做到这一点,请创建TableSequence的子类并覆盖buildSelectQuery()方法,以添加“+1”(或“-1”)到SQL中,以解决假设差异。然后,您可以使用SessionCustomizer添加自定义序列。还请在EclipseLink中记录错误,以添加OpenJPA序列的兼容选项。

没错,我不能触及非JPA用法。子类化TableSequence似乎是一个聪明的方法,我会尝试并告诉你结果。 - jacoviza
那绝对有效。插入操作没有冲突,JPA 和非 JPA 实现之间也没有缺失 ID。非常感谢! - jacoviza

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