2014-11-03 38 views
2

我有一些類型爲varchar[]的列的postgres數據庫。 jOOQ和pgjdbc-ng不是很好玩; jOOQ的DefaultBindContext沿着線的東西:是否可以編寫一個jOOQ轉換器應用於數組?

protected final BindContext bindValue0(Object value, Field<?> field) throws SQLException { 
    SQLDialect dialect = configuration.dialect(); 

    // [#650] [#3108] Use the Field's Converter before actually binding any value 
    Converter<?, ?> converter = field.getConverter(); 
    Class<?> type = converter.fromType(); 
    value = ((Converter) converter).to(value); 

    //... 

    else if (type.isArray()) { 
     switch (dialect) { 
      case POSTGRES: { 
       stmt.setString(nextIndex(), toPGArrayString((Object[]) value)); 
       break; 
      } 

哪個聲明變量設置爲"{\"value1\", \"value2\", \"etc\"}",這是你將怎樣指定查詢的數組。後來,pgjdbc-NG具有:

public static Object coerceToArray(Format format, Object val, Type type, Class<?> targetType, Map<String, Class<?>> typeMap, PGConnectionImpl connection) throws SQLException { 
    if (val == null) { 
    return null; 
    } 
    else if (val instanceof PGArray) { 
    return coerceToArray(format, ((PGArray) val).getValue(), type, targetType, typeMap, connection); 
    } 
    else if (val.getClass().isArray()) { 
    return coerceToArray(format, val, 0, Array.getLength(val), type, targetType, typeMap, connection); 
    } 

    throw createCoercionException(val.getClass(), targetType); 
} 

哪個預計,在語句中的值將是任一類型PGArray或實際陣列;它無法強制將數組的字符串表示形式轉換爲數組的字符串表示形式。 :(

我想寫一個jOOQ轉換器,將String[]PGArray之間的轉換;理想情況下,這將意味着jOOQ的DefaultBindContext將離開轉換值不夠好孤單,然後pgjdbc-NG將能夠處理它。正確

不過,我一直無法寫jOOQ架構配置,可以讓我做這件事我已經嘗試了變化:

<customType>  
    <customType> 
     <name>StringArray</name> 
     <type>java.lang.String[]</type> 
     <converter>my.package.PGStringArrayConverter</converter> 
    </customType> 
</customTypes> 

<forcedTypes> 
    <forcedType> 
     <name>StringArray</name> 
     <types>varchar\[\]</types> 
    </forcedType> 
</forcedTypes> 

沒有任何運氣;生成的表對象是指a String[][]varchar[]在任何東西上都不匹配。即使我把它分解下來,這樣的強制類型匹配任何類型,但<expression>只匹配我的列,並且轉換器的類型是java.lang.String,我最終與java編譯器抱怨無法將Object []轉換爲字符串[]。

隧道盡頭有燈還是我應該開始遷移我的數據庫?

回答

1

所以,事實證明答案是「有點」。

我正在創建我的PGStringArrayConverter類向後;我創造了

public abstract class PGArrayConverter implements Converter<String[], PGArray> 

什麼結束了工作是:

public abstract class PGArrayConverter implements Converter<Object, String[]> { 
    @Override 
    public String[] from(final Object databaseObject) { 
     if (databaseObject == null) { 
      return null; 
     } 
     if (databaseObject.getClass().isArray()) { 
      return (String[]) databaseObject; 
     } 
     return (String[]) ((PGArray)databaseObject).getValue(); 
    } 

    @Override 
    public Object to(final String[] userObject) { 
     if (userObject == null) { 
      return null; 
     } 
     return new PGArray(null, null, userObject); 
    } 

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

    @Override 
    public Class<String[]> toType() { 
     return String[].class; 
    } 
} 

from()變成了一種奇怪的;我得到了字符串數組,而不是PGArray。我不認爲數據庫意識到它「應該」將它們序列化到PGArray中。

我還不得不修改生成的代碼,這有點令人討厭。我Schema.xml文件包含:

<customType> 
    <name>StringArray</name> 
    <type>java.lang.String</type> 
    <converter>my.package.PGStringArrayConverter</converter> 
</customType> 

<forcedType> 
    <name>StringArray</name> 
    <expression>.*tabular_answer_entry.text.*</expression> 
    <types>.*</types> 
</forcedType> 

我不得不改變所生成的表格文件,以消除對createField的數據類型.getArrayDataType()電話:

public final org.jooq.TableField<my.package.gen.tables.records.TabularAnswerEntryRecord, java.lang.String[]> TEXT = createField("text", org.jooq.impl.DefaultDataType.getDefaultDataType("java.lang.String").getArrayDataType(), this, "", new my.package.PGStringArrayConverter()); 

到:

public final org.jooq.TableField<my.package.gen.tables.records.TabularAnswerEntryRecord, java.lang.String[]> TEXT = createField("text", org.jooq.impl.DefaultDataType.getDefaultDataType("java.lang.String"), this, "", new my.package.PGStringArrayConverter()); 

整個解決方案感覺有些不好意思,我將不得不寫一個單元測試的怪物,以確保在更新任何相關軟件包時這不會中斷,但至少我能夠o讀取並寫入我的數據庫。