Java JOOQ-调用Record.update()时发生DataChangedException?
我想我缺少了一些关于Java JOOQ-调用Record.update()时发生DataChangedException?,java,sql,jooq,Java,Sql,Jooq,我想我缺少了一些关于updateablerecord.update()工作原理的主要内容 不起作用的示例代码: MailKeywordRealAddressRecord linkRecord = dsl.select(). from(MAIL_KEYWORD_REAL_ADDRESS). where(MAIL_KEYWORD_REAL_ADDRESS.MAIL_KEYWORD_ID.eq(mailKeyword.getId())). fetchOneInto(MailKeywordR
updateablerecord.update()
工作原理的主要内容
不起作用的示例代码:
MailKeywordRealAddressRecord linkRecord = dsl.select().
from(MAIL_KEYWORD_REAL_ADDRESS).
where(MAIL_KEYWORD_REAL_ADDRESS.MAIL_KEYWORD_ID.eq(mailKeyword.getId())).
fetchOneInto(MailKeywordRealAddressRecord.class);
if( linkRecord == null ){
log.debug("no link record found for our mailKeyword");
linkRecord = dsl.newRecord(MAIL_KEYWORD_REAL_ADDRESS);
linkRecord.setMailKeywordId(mailKeyword.getId());
linkRecord.setRealAddressId(realAddress.getId());
linkRecord.insert();
}
else {
// 1 - will geta "DataChangedException" because it tries to do a
// "select ... for udpate" with the *new* realAddress id
log.debug("updating old linkRecord from: {}", linkRecord );
linkRecord.setRealAddressId(realAddress.getId());
linkRecord.update();
// 2 - working
// log.debug("updating old linkRecord from: {}", linkRecord );
// linkRecord.delete();
// linkRecord.setRealAddressId(realAddress.getId());
// linkRecord.insert();
}
这将导致异常:
DataChangedException:数据库记录不再存在
如果我看一下SQL,JOOQ正在使用RealAddressId的new值发出一个selectforupdate
SQL语句
如果我注释掉(1)块并使用(2)-JOOQ似乎做了我想做的事情,它会删除旧记录并更新新记录
MailKeywordRealAddressRecord下面的表是一个普通的多对多链接表(两列,都声明为复合主键)
想想看…-这就是问题所在吗?我正在更新主键列?
我很高兴能够坚持使用delete/insert逻辑(或者我可以重构为直接SQL语句),只是想弄清楚到底发生了什么
数据库是Postgres,JOOQ版本是3.10.1。一般建议:使用INSERT。。关于冲突
您当前的逻辑可能会遇到竞争条件,并且通常有点太乏味而无法编写。jOOQ支持PostgreSQL的INSERT。。在冲突时更新
语法,它将UPSERT的处理委托给数据库,这通常是您更喜欢的,除非您确实依赖乐观锁定,而在当前的代码示例中您似乎没有这样做
回答你的问题
我认为这只是因为误解了jOOQ的乐观锁定功能,另请参见手册:
- ExecuteThoOptimisticLocking:这允许完全关闭功能
- executeWithOptimisticLockingExcludeUnversioned:这允许关闭未明确版本控制的可更新记录的功能
updateablerecords
,也会启用乐观锁定。在这种情况下,在执行乐观锁定检查时验证整个记录。这可能不是您想要的,因此您应该将此标志设置为true
一般建议:使用INSERT。。关于冲突
您当前的逻辑可能会遇到竞争条件,并且通常有点太乏味而无法编写。jOOQ支持PostgreSQL的INSERT。。在冲突时更新
语法,它将UPSERT的处理委托给数据库,这通常是您更喜欢的,除非您确实依赖乐观锁定,而在当前的代码示例中您似乎没有这样做
回答你的问题
我认为这只是因为误解了jOOQ的乐观锁定功能,另请参见手册:
- ExecuteThoOptimisticLocking:这允许完全关闭功能
- executeWithOptimisticLockingExcludeUnversioned:这允许关闭未明确版本控制的可更新记录的功能
出于向后兼容性的原因,默认情况下这两个标志都处于关闭状态。如果启用乐观锁定,则默认情况下,对于未显式配置版本字段的
updateablerecords
,也会启用乐观锁定。在这种情况下,在执行乐观锁定检查时验证整个记录。这可能不是您想要的,因此您应该将此标志设置为true
您是否正在使用设置。是否执行OptimisticLockingCludeReversioned
功能?当您打开该功能时,您的期望是什么?@Lukase在这里可以找到JOOQ codegen设置:在我的Spring设置中,JOOQ设置被配置为“WithExecuteThooptimisticLocking(true)”。就我对该功能的期望而言,我不会假设它与没有版本字段的记录相关。好吧,该功能实际上是说:“使用乐观锁定执行,包括那些没有版本字段的记录”。我将提供一个答案。您是否正在使用设置。执行OptimisticLockingCludeInversion
功能?当您打开该功能时,您的期望是什么?@Lukase在这里可以找到JOOQ codegen设置:在我的Spring设置中,JOOQ设置被配置为“WithExecuteThooptimisticLocking(true)”。就我对该功能的期望而言,我不会假设它与没有版本字段的记录相关。好吧,该功能实际上是说:“使用乐观锁定执行,包括那些没有版本字段的记录”。我会提供一个答案。