java - 字符变化列的自定义转换器 - from 方法中的参数为 null

标签 java sql jooq

我遇到了与自定义转换器和字符串值相关的问题。

设置:

JOOQ 版本 - 3.11.0

maven 插件中的forcedTypes 部分:

<forcedType>
    <userType>com.test.SomeObject</userType>
    <converter>com.test.SomeObjectConverter</converter>
    <expression>some_object</expression>
    <types>.*</types>
</forcedType>

some_object sql 定义:

some_object character varying(255) NOT NULL

转换器本身:

public class SomeObjectConverter implements Converter<String, SomeObject> {

    @Override
    public SomeObject from(final String s) {
        return new SomeObject(s);
    }

    @Override
    public String to(final SomeObject someObject) {
        return someObject.getFieldsThatsString();
    }

    @Override
    public Class<String> fromType() {
        return String.class;
    }

    @Override
    public Class<SomeObject> toType() {
        return SomeObject.class;
    }
}

生成的 JOOQ 记录中的字段类型正确

public final TableField<SomeTableRecord, SomeObject> SOME_OBJECT

不幸的是,当我执行查询时

dslContext.insertInto(SOME_TABLE)
            .set(SOME_TABLE.SOME_OBJECT, new SomeObject("string")).execute();

SomeObjectConverter 无法正确处理此问题,因为 from 方法中的参数 final String s 为 null,这会导致意外行为

编辑:堆栈跟踪:

java.lang.NullPointerException
    at com.test.SomeObject.<init>(SomeObject.java:16)
    at com.test.SomeObjectConverter.from(HierarchyIdConverter.java:10)
    at com.test.SomeObjectConverter.from(HierarchyIdConverter.java:6)
    at org.jooq.impl.ConvertedDataType.convert(ConvertedDataType.java:105)
    at org.jooq.impl.DSL.val(DSL.java:19800)
    at org.jooq.impl.DSL.val(DSL.java:19769)
    at org.jooq.impl.FieldMapsForInsert.addFields(FieldMapsForInsert.java:287)
    at org.jooq.impl.FieldMapsForInsert.set(FieldMapsForInsert.java:315)
    at org.jooq.impl.FieldMapsForInsert$2.put(FieldMapsForInsert.java:402)
    at org.jooq.impl.FieldMapsForInsert$2.put(FieldMapsForInsert.java:368)
    at org.jooq.impl.AbstractStoreQuery.addValue(AbstractStoreQuery.java:85)
    at org.jooq.impl.InsertImpl.set(InsertImpl.java:688)
    at org.jooq.impl.InsertImpl.set(InsertImpl.java:126)
    at com.test.Repository.insertSomeObject(Repository.java:26)

最佳答案

这是 jOOQ 中的一个错误:https://github.com/jOOQ/jOOQ/issues/7742

jOOQ 使用 null 参数调用转换器的原因是,在多行 INSERT 语句的情况下,不会在每行上设置相同的列,每行上缺少的列需要有一个占位符绑定(bind)值。示例:

dslContext.insertInto(SOME_TABLE)
          .set(SOME_TABLE.SOME_OBJECT, new SomeObject("string"))
          .newRecord()
          .set(SOME_TABLE.SOME_OTHER_OBJECT, "other")
          .execute();

在上述情况下,第二行需要为 SOME_OBJECT 列生成 null 值,以便插入语句在语法上正确。

当然,就您而言,这不应该适用。 null 值初始化应该在 jOOQ 内部更加延迟地实现。

解决方法

使您的转换器null安全,例如:

public class SomeObjectConverter implements Converter<String, SomeObject> {

    @Override
    public SomeObject from(final String s) {
        return s == null ? null : new SomeObject(s);
    }

    @Override
    public String to(final SomeObject s) {
        return s == null ? null : s.getFieldsThatsString();
    }

    ...
}

关于java - 字符变化列的自定义转换器 - from 方法中的参数为 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51769846/

相关文章:

java - 我如何使用通配符在java servlet中映射url

java - 将 <%@include%> 与 apachetiles 这样的库一起使用是否正常?

mysql - 将 CSV 导入 MySQL - 偏移 1 列

java - 限制和偏移的jooq问题

java - 将 JPanel 添加到 JScrollPane

sql - 在 SQL 中从下到上将给定数量分配给负值列表

sql - 创建一个触发器,它将在更新另一个表时将记录插入表中

java - 是否可以将MyBatis和QueryDSL/jOOQ结合使用?

java - 如何在 jooq 中选择一个自动生成的记录和附加数据?

java - 将 Spring boot/cloud 与 Amazon AWS lambda 一起使用不会注入(inject)值