fetchInto

时间:2018-11-09 19:45:34

标签: java jooq

这是一个奇怪的问题,在JOOQ的3.10和3.11版本中一直发生(没有尝试更早的版本)。我使用fetchInto获取记录,当我打印记录(或调试)时,所有字段均正确打印。也就是说,field_x的值是正确的。

问题在于,当我使用记录的getX方法检索field_x时,它将从另一个字段返回该值。

下面是我们使用的一些代码。

        return jooqDslContext.select(CL_USERS.fields())
            .from(CL_USERS)
            .join(THIRDPARTY_USER_XREF)
            .on(THIRDPARTY_USER_XREF.USER_ID.eq(CL_USERS.CL_USER_ID))
            .join(THIRDPARTY_USER_ID)
            .on(THIRDPARTY_USER_ID.ID.eq(THIRDPARTY_USER_XREF.THIRDPARTY_ID))
            .where(THIRDPARTY_USER_ID.EID.eq(eid))
            .fetchOptionalInto(CL_USERS);

这是记录的打印。...

+--------------------------------------------------+----------+------+-----------+------------------+------------+----------------+------------------------+ etc... 
|remember_token                                    |cl_user_id|ria_id|ria_user_id|ria_user_id_backup|cl_user_type|user_description|first_name              | etc...
+--------------------------------------------------+----------+------+-----------+------------------+------------+----------------+------------------------+ etc...
|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...| 777777777|   777|      77777|            {null}|      {null}|{null}          |xxxxxxxxxxxxxxxxxxxxxxxx| etc...
+--------------------------------------------------+----------+------+-----------+------------------+------------+----------------+------------------------

注意first_name已填充。但是当我使用first_name方法打印getFirstName时,我得到了NULL

cur.getFirstName() = null

从外观上看,字段的索引号似乎不匹配...。在这种情况下,生成的代码认为firstName是字段6,但实际上是字段8( toString()输出中的第8个字段。

    public byte[] getFirstName() {
        return (byte[]) get(6);
    }

编辑:添加更多信息。

  

该如何复制?

这是另一个使用与以上示例不同的代码库的示例。在这种情况下,我在记录对象上设置了amount字段。但是当我保存或打印时,将设置address字段。

    TransactionsRecord tr = serviceDslContext.newRecord(Transactions.TRANSACTIONS);
    tr.setAmount(new BigDecimal(10));
    logger.debug("tr = {}", tr);

打印..

+------+-------+-------+...
|amount|account|address|...
+------+-------+-------+...
|{null}|{null} |*10    |...
+------+-------+-------+...

Link to the JOOQ generated code.

  

您可以发布表格的DDL吗?

CREATE TABLE `transactions` (
    `account` VARCHAR(50) NOT NULL,
    `address` VARCHAR(50) NOT NULL,
    `amount` DECIMAL(42,10) NOT NULL,
    `bip125-replaceable` VARCHAR(64) NOT NULL,
    `blockhash` VARCHAR(64) NOT NULL,
    `blockindex` INT(11) NOT NULL,
    `blocktime` TIMESTAMP NULL DEFAULT NULL,
    `category` VARCHAR(50) NOT NULL,
    `confirmation` INT(11) NOT NULL,
    `generated` TINYINT(1) NOT NULL,
    `instantlock` TINYINT(4) NOT NULL,
    `involvesWatchonly` TINYINT(4) NOT NULL,
    `label` VARCHAR(50) NOT NULL,
    `time` TIMESTAMP NULL DEFAULT NULL,
    `timereceived` TIMESTAMP NULL DEFAULT NULL,
    `txid` VARCHAR(64) NOT NULL,
    `vout` INT(11) NOT NULL,
    `walletconflicts` TEXT NULL,
    `amount_in_usd` DECIMAL(42,10) NULL DEFAULT NULL,
    `usd_exchange_rate` DECIMAL(42,10) NULL DEFAULT NULL,
    PRIMARY KEY (`txid`),
    INDEX `account_generated` (`account`, `generated`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
;
  

您正在使用什么数据库产品和版本?

在上述情况下,我在AWS RDS上使用MySQL 5.7.23。对于第一个示例,它是AWS RDS上MySQL 5.6的变体。另外,对于后一个示例,它发生在5.7.14-google上,我们最近迁移到了AWS。

2 个答案:

答案 0 :(得分:1)

您发布的生成记录似乎是手动或使用某些后期处理程序修改的,或者是由自定义生成器生成的。显然,生成的表(正确的顺序):

public class Transactions extends TableImpl<TransactionsRecord> {

    ...

    public final TableField<TransactionsRecord, BigDecimal> AMOUNT = 
      createField("amount", org.jooq.impl.SQLDataType.DECIMAL(42, 10).nullable(false), this, "");

    public final TableField<TransactionsRecord, String> ACCOUNT = 
      createField("account", org.jooq.impl.SQLDataType.VARCHAR(50).nullable(false), this, "");

    public final TableField<TransactionsRecord, String> ADDRESS = 
      createField("address", org.jooq.impl.SQLDataType.VARCHAR(50).nullable(false), this, "");

    ...

...以及生成的记录:

public class TransactionsRecord extends UpdatableRecordImpl<TransactionsRecord> 
    implements Record20<...> {

    public void setAccount(String value) {
        set(0, value);
    }

    public String getAccount() {
        return (String) get(0);
    }

    public void setAddress(String value) {
        set(1, value);
    }

    public TransactionsRecord() {
        super(Transactions.TRANSACTIONS);
    }

    public TransactionsRecord(String account, String address, BigDecimal amount, ...) {
        super(Transactions.TRANSACTIONS);

        set(0, account);
        set(1, address);
        set(2, amount);
        ...
    }

    public BigDecimal getAmount() {
        return (BigDecimal) get(2);
    }

    public String getAddress() {
        return (String) get(1);
    }

    public void setAmount(BigDecimal value) {
        set(2, value);
    }

    public void setBlockhash(String value) {
        set(4, value);
    }

    ...

...不匹配。看一下在构造函数之前在之前有getter和setter的方法。另外,它们也不正常! jOOQ提供的官方JavaGenerator不会生成此类。

注意,如果您确实想修改生成的代码,则应该覆盖JavaGenerator或实现自己的生成器类。

答案 1 :(得分:1)

进行一些测试后,看起来IntelliJ中的Rearrange code功能正在弄乱JOOQ生成的代码。这会对生产中运行的代码产生可怕的后果。 Rearrange code功能在“提交更改”窗口中显示为一个选项。

enter image description here

测试包括在Rearrange code功能之前和之后运行测试。下面是代码。

    TransactionsRecord tr = serviceDslContext.newRecord(TRANSACTIONS);
    tr.setAmount(new BigDecimal(10));
    logger.debug("tr = {}", tr);

如果此代码在Rearrange code功能之前执行,即在JOOQ生成代码后立即执行,则显示以下内容...

 +-------+-------+------+...
|account|address|amount|...
+-------+-------+------+...
|{null} |{null} |   *10|...
+-------+-------+------+...

IntelliJ在JOOQ生成的代码上执行Rearrange code之后,这就是输出...

+------+-------+-------+...
|amount|account|address|...
+------+-------+-------+...
|{null}|{null} |*10    |...
+------+-------+-------+...

这些值似乎停留在正确的位置,但是这些值所代表的字段已经转移了。