我正在开发一个项目,我们最近将持久性提供程序从使用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
OpenJPA的
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]
提前致谢!
答案 0 :(得分:1)
问题不是更新与选择的顺序,而是具有当前值的解释。 EclipseLink假定它获取当前值,而OpenJPA似乎没有。
理想情况下,您可以更改非JPA用法以进行相同的假设。如果不能,您可以在EclipseLink中编写自己的自定义Sequence对象。
为此,请创建TableSequence的子类并覆盖buildSelectQuery()方法,以向SQL添加“+ 1”(或“ - 1”),以说明假设的差异。
然后,您可以使用SessionCustomizer添加自定义序列。
还请在EclipseLink中记录一个错误,为OpenJPA排序添加兼容性选项。