2014-11-03 3 views
2

나는 varchar[] 유형의 일부 열이있는 postgres 데이터베이스를 가지고 있습니다. jOOQ와 pgjdbc-ng는 멋지게 함께 연주하지 않습니다. 쿼리의 배열을 지정하는 것입니다 방법 인 "{\"value1\", \"value2\", \"etc\"}"에 문 변수를 설정배열에 적용 할 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; 
      } 

: jOOQ의 DefaultBindContext이의 라인을 따라 뭔가가있다. 나중에, pgjdbc-NG가 있습니다

문에 값이 두 유형 PGArray 또는 실제 배열이 될 것으로 예상하고
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); 
} 

; 배열의 문자열 표현을 배열의 문자열 표현으로 강제 변환하지 못합니다. :(나는 String[]PGArray 사이의 변환하는 jOOQ 변환기를 작성하는 것을 시도하고있다

, 이상적으로,이 jOOQ의 DefaultBindContext 혼자 충분히 변환 된 값을 떠날 것을 의미하고 pgjdbc-ng에 그것을 처리 할 수있을 것 .. 운이없이

<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> 

, 생성 된 테이블 개체를 참조하십시오 제대로

그러나, 나는 나에게이 작업을 수행 할 수있는 jOOQ 스키마 구성을 쓸 수 없었다 나는에 변화를 시도했다 a String[][]varchar[] 아무것도 일치하지 않습니다. 비록 내가 그것을 무너 뜨리고, forcedType이 모든 유형에 일치하지만 <expression>이 내 열과 일치하고 변환기 유형이 java.lang.String 인 경우에도 Java 컴파일러가 Object []를 String으로 형변환 할 수 없다는 불평을하게됩니다. [].

이 터널 끝 부분에 표시등이 있습니까? 아니면 데이터베이스 마이그레이션을 시작해야합니까?

답변

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() 이상한의 종류 밝혀졌다; 나는 PGArrays보다는 Strings 배열을 얻고 있었다. 필자는 데이터베이스가 PGArrays로 직렬화한다고 가정하고 있다고 생각하지 않습니다.

나는 또한 약간 불쾌한 생성 된 코드를 수정해야했습니다. 내의 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 데이터베이스에서 읽고 쓴다.

관련 문제