代码之家  ›  专栏  ›  技术社区  ›  lukaszrys

from方法中字符可变列参数的自定义转换器为空

  •  1
  • lukaszrys  · 技术社区  · 7 年前

    我有一个与自定义转换器和字符串值有关的问题。

    设置:

    JOOQ版本-3.11.0

    maven插件中的forcedTypes部分:

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

    某些对象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 方法为空,将导致意外行为

    编辑:堆栈跟踪:

    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 回复  |  直到 7 年前
        1
  •  1
  •   Lukas Eder    7 年前

    这是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();
    

    在上述情况下,第二行需要产生 无效的 价值 SOME_OBJECT insert语句语法正确的列。

    当然,在你的情况下,这不应该适用。这个 无效的 值初始化应该在jOOQ内部更懒地实现。

    解决办法

    制作转换器 无效的 安全,例如:

    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();
        }
    
        ...
    }