尝试使用 POJO 记录更新表时出现 Java jOOQ 问题

Posted

技术标签:

【中文标题】尝试使用 POJO 记录更新表时出现 Java jOOQ 问题【英文标题】:Java jOOQ issue when trying to update a table using a POJO Record 【发布时间】:2018-11-22 01:03:21 【问题描述】:

我正在尝试执行一个简单的 updateRecord 函数,但它给了我一个错误,我找不到原因或任何其他人有它。

可以在以下位置找到示例测试项目: https://github.com/billbarni/jooq-studer-h2-test

Java 代码:

import static mypackage.database.model.h2.public_.Tables.EXPRESSAO;
import mypackage.database.model.h2.public_.tables.pojos.Expressao;
import mypackage.database.model.h2.public_.tables.records.ExpressaoRecord;

public void updateQuery(Expressao expressaoPojo) 
  ExpressaoRecord expressaoRecord = ctx.newRecord(EXPRESSAO, expressaoPojo);
  ctx.executeUpdate(expressaoRecord); // Error with this parameter

数据库创建表达式:

CREATE TABLE
 expressao (
  id INT AUTO_INCREMENT PRIMARY KEY NOT NULL,
  nome VARCHAR(50) NOT NULL,
  conteudo VARCHAR NOT NULL,
  qtd_tempo INT NOT NULL,
  tipo_tempo VARCHAR(5) NOT NULL,
  data_inicial TIMESTAMP NOT NULL
 );

Gradle 生成器配置:

plugins 
    id 'nu.studer.jooq' version '2.0.9'


dependencies 
    compile group: 'org.jooq', name: 'jooq-codegen', version: '3.10.4'
    jooqRuntime 'com.h2database:h2:1.4.197'


jooq 
    h2(sourceSets.main) 
        jdbc 
            driver = 'org.h2.Driver'
            url = 'jdbc:h2:file:./db'
            user = 'sa'
            password = ''
        
        generator 
            name = 'org.jooq.util.DefaultGenerator'
            strategy 
                name = 'org.jooq.util.DefaultGeneratorStrategy'
            
            database 
                name = 'org.jooq.util.h2.H2Database'
            
            generate 
                relations = true
                deprecated = false
                records = true
                immutablePojos = true
                fluentSetters = true
            
            target 
                packageName = 'mypackage.database.model.h2'
                directory = 'src/main/java'
            
        
    

Java 在编译之前给了我这个错误:

DSLContext 中的executeUpdate (R) 无法应用于 (mypackage.database.model.h2.public_.tables.records.ExpressaoRecord) 原因:不存在类型变量 R 的实例,因此 ExpressaoRecord 符合 UpdatableRecord

这个问题背后的原因是什么?我做错了什么?

Obs.:我有 2 个数据库(firebird 和 h2),我使用 Gradle 的 jOOQ 生成器自动生成 pojos 和其他类。他们不共享 POJO 或任何复杂的东西。这个项目非常小而且简单。

Obs 2.:我使用了多个版本的 jOOQ 库(从 3.9 到新的 3.11),问题仍然存在。

Lukas Eder,jOOQ 之神,我等待你的归来,将我从这冗长的沉睡中解救出来。

【问题讨论】:

我来为您解除痛苦。您可以发布EXPRESSAO 表的 DDL (CREATE TABLE) 吗? 备案,这个问题也已经反馈给gradle-jooq-plugin:github.com/etiennestuder/gradle-jooq-plugin/issues/73 【参考方案1】:

DSLContext.executeUpdate(R) 要求 RUpdatableRecord 的子类型,这是有道理的。只有“可更新”(即知道其主键)的记录才能有效更新。

您的ExpressaoRecord 似乎不是UpdatableRecord,而只是TableRecord。这可能有几个原因:

您在代码生成器中停用了<relations/> 标志

<relations>false</relations>可以用来关闭所有关系相关特征的生成,包括主键、外键信息。如果没有这些信息,您实际上无法生成UpdatableRecord 类型。

您的表没有主键。

没有主键,代码生成器不会生成UpdatableRecord

您可以向表中添加一个主键,或者告诉代码生成器一个“合成主键”:

https://www.jooq.org/doc/latest/manual/code-generation/codegen-advanced/codegen-config-database/codegen-database-synthetic-primary-keys/

或者,您可以通过将任何唯一键视为主键来“覆盖”您的主键:

https://www.jooq.org/doc/latest/manual/code-generation/codegen-advanced/codegen-config-database/codegen-database-override-primary-keys/

【讨论】:

抱歉,我花了这么长时间才更新我的问题。我的表的 CREATE 现在包括在内。也许我应该使用其他sintax呢? H2 接受了那个,但在列标志中做错了什么? @MBarni:好的,所以假设 #1 尚未得到证实。你能发布你的代码生成配置吗? 使用 gradle 配置更新的问题。我正在使用第三方插件,可能是导致问题的原因? @MBarni:在第三方插件中,这将是一个非常重要的问题,您不会是唯一遭受它的人,所以我将其排除为可能的原因。此外,您的配置看起来正确。再检查一件事:您的ExpressaoRecord 是否扩展UpdatableRecordImpl?如果您删除 includes 规范,问题是否仍然存在? @MBarni:这真的很奇怪。明天我会尝试重现这个。毕竟这可能是第三方插件的问题......【参考方案2】:

问题似乎出在nu.studer.jooq 插件上,因为当使用另一个代码生成器时,反映具有主键的表的 H2 数据库模型类会收到 UpdatableTable 扩展/实现。

我在插件上开了一个issue,想要关注的可以在上面已经链接几行的插件github页面查看open issues。

插件的新版本(版本 3.x+)似乎已经解决了这个问题。升级时要小心,因为插件配置中有许多重大更改,它也会强制使用新的 jOOQ 版本(3.11+)。

【讨论】:

以上是关于尝试使用 POJO 记录更新表时出现 Java jOOQ 问题的主要内容,如果未能解决你的问题,请参考以下文章

尝试在存储过程中更新时出现 MySQL 错误代码 1175

CloudKit-更新记录:使用“saveRecord”更新记录时出现“客户端 oplock 错误”

使用 oledbcommand.executeNonQuery() 更新 MS Access 记录时出现问题,结果未更新

更新记录时出现 Django IntegrityError

更新相互链接的三个表时出现问题

尝试创建我的第一个 oracle 触发器时出现问题