java - JOOQ - 调用 Record.update() 时出现 DataChangedException?

标签 java sql jooq

我认为我错过了有关 UpdatableRecord.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: Database record no longer exists

如果我查看 SQL,JOOQ 会使用 RealAddressId 的 new 值发出 select for update SQL 语句。

如果我注释掉 (1) block 并使用 (2) - JOOQ 似乎可以执行我想要的操作,它会删除旧记录并更新新记录。

MailKeywordRealAddressRecord 下面的表是一个普通的多对多链接表(两列,均被声明为复合主键)。

想一想... - 这是问题所在吗?我正在更新主键列? 我很高兴坚持使用删除/插入逻辑(或者我可以重构为直接 SQL 语句) - 只是想弄清楚发生了什么。

数据库是Postgres,JOOQ版本是3.10.1。

最佳答案

一般建议:使用INSERT .. ON CONFLICT

您当前的逻辑可能会遇到竞争条件,并且通常编写起来有点乏味。 jOOQ 支持 PostgreSQL 的 INSERT .. ON CONFLICT DO UPDATE 语法,该语法将 upsert 的处理委托(delegate)给数据库,您通常应该更喜欢这种方式,除非您确实依赖于乐观锁定,而您在当前的代码示例中似乎没有这样做

回答您的问题

我认为这只是源于对 jOOQ 乐观锁定功能的误解,另请参阅手册:

There are two settings governing the behaviour of the jOOQ optimistic locking feature:

  • executeWithOptimisticLocking: This allows for turning off the feature entirely.
  • executeWithOptimisticLockingExcludeUnversioned: This allows for turning off the feature for updatable records who are not explicitly versioned.

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

关于java - JOOQ - 调用 Record.update() 时出现 DataChangedException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47108449/

相关文章:

gradle - 从JOOQ Code Gen Config xml中的属性文件读取值

java - 使用 jOOq 时如何将参数值用括号括起来?

javascript - 将 p5js 草图转换为处理的问题

java - java.awt.Graphics.drawLine 如何工作?

java - 有没有办法在 JBoss 7.1.1 中记录 HTTP 发布数据?

sql - MySQL:FULL OUTER JOIN - 如何合并一列?

java - 从 JOOQ 中的代码生成中排除特定模式

java - Eclipse 将不在工作区中的项目的文件保存在哪里?

MySQL 数据库。无法添加外键

mysql - 优化查询 : Select in Select