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

时间:2018-08-09 14:38:44

标签: java sql jooq

我遇到了与自定义转换器和String值有关的问题。

设置:

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无法正确处理此问题,因为final String s方法中的参数from为空,这会导致意外行为

编辑:Stacktrace:

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)

1 个答案:

答案 0 :(得分:1)

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

jOOQ使用null参数调用转换器的原因是因为在多行INSERT语句中,每行没有设置相同的列,因此需要每行缺少的列的占位符绑定值。示例:

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

在上述情况下,第二行需要为null列产生一个SOME_OBJECT值,以使insert语句在语法上正确。

当然,就您而言,这不适用。 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();
    }

    ...
}