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的乐观锁定功能,另请参见手册:

有两种设置控制jOOQ乐观锁定功能的行为:

  • ExecuteThoOptimisticLocking:这允许完全关闭功能
  • executeWithOptimisticLockingExcludeUnversioned:这允许关闭未明确版本控制的可更新记录的功能
出于向后兼容性的原因,默认情况下这两个标志都处于关闭状态。如果启用乐观锁定,则默认情况下,对于未显式配置版本字段的
updateablerecords
,也会启用乐观锁定。在这种情况下,在执行乐观锁定检查时验证整个记录。这可能不是您想要的,因此您应该将此标志设置为
true

一般建议:使用
INSERT。。关于冲突
您当前的逻辑可能会遇到竞争条件,并且通常有点太乏味而无法编写。jOOQ支持PostgreSQL的
INSERT。。在冲突时更新
语法,它将UPSERT的处理委托给数据库,这通常是您更喜欢的,除非您确实依赖乐观锁定,而在当前的代码示例中您似乎没有这样做

回答你的问题 我认为这只是因为误解了jOOQ的乐观锁定功能,另请参见手册:

有两种设置控制jOOQ乐观锁定功能的行为:

  • ExecuteThoOptimisticLocking:这允许完全关闭功能
  • executeWithOptimisticLockingExcludeUnversioned:这允许关闭未明确版本控制的可更新记录的功能

出于向后兼容性的原因,默认情况下这两个标志都处于关闭状态。如果启用乐观锁定,则默认情况下,对于未显式配置版本字段的
updateablerecords
,也会启用乐观锁定。在这种情况下,在执行乐观锁定检查时验证整个记录。这可能不是您想要的,因此您应该将此标志设置为
true

您是否正在使用
设置。是否执行OptimisticLockingCludeReversioned
功能?当您打开该功能时,您的期望是什么?@Lukase在这里可以找到JOOQ codegen设置:在我的Spring设置中,JOOQ设置被配置为“WithExecuteThooptimisticLocking(true)”。就我对该功能的期望而言,我不会假设它与没有版本字段的记录相关。好吧,该功能实际上是说:“使用乐观锁定执行,包括那些没有版本字段的记录”。我将提供一个答案。您是否正在使用
设置。执行OptimisticLockingCludeInversion
功能?当您打开该功能时,您的期望是什么?@Lukase在这里可以找到JOOQ codegen设置:在我的Spring设置中,JOOQ设置被配置为“WithExecuteThooptimisticLocking(true)”。就我对该功能的期望而言,我不会假设它与没有版本字段的记录相关。好吧,该功能实际上是说:“使用乐观锁定执行,包括那些没有版本字段的记录”。我会提供一个答案。