I want to use Collections in java instead of arrays to serialize postgreSQL arrays. Such as int[], varchar(256)[] to java Collection and Collection.
I use jooq 3.6.2, java 8 and postgresql 9.2.9.
I tried to implement custom binding:
public class PostgresArrayBinding implements Binding<Object, Collection> {
@Override
public Converter<Object, Collection> converter() {
return new Converter<Object, Collection>() {
@Override
public Collection from(final Object dbObj) {
return dbObj == null ? null : new ArrayList<>(Arrays.asList((Object[])dbObj));
}
@Override
public Object to(final Collection userObject) {
return userObject == null ? null : "ARRAY[" + Joiner.on(',').join(userObject) + "]";
}
@Override
public Class<Object> fromType() {
return Object.class;
}
@Override
public Class<Collection> toType() {
return Collection.class;
}
};
}
@Override
public void sql(final BindingSQLContext<Collection> ctx) throws SQLException {
ctx.render().visit(DSL.val(ctx.convert(converter()).value())).sql("::ARRAY");
}
@Override
public void register(final BindingRegisterContext<Collection> ctx) throws SQLException {
ctx.statement().registerOutParameter(ctx.index(), Types.ARRAY);
}
@Override
public void set(final BindingSetStatementContext<Collection> ctx) throws SQLException {
ctx.statement().setString(ctx.index(), Objects.toString(ctx.convert(converter()).value(), null));
}
@Override
public void set(final BindingSetSQLOutputContext<Collection> ctx) throws SQLException {
throw new SQLFeatureNotSupportedException();
}
@Override
public void get(final BindingGetResultSetContext<Collection> ctx) throws SQLException {
ctx.convert(converter()).value(ctx.resultSet().getString(ctx.index()));
}
@Override
public void get(final BindingGetStatementContext<Collection> ctx) throws SQLException {
ctx.convert(converter()).value(ctx.statement().getString(ctx.index()));
}
@Override
public void get(final BindingGetSQLInputContext<Collection> ctx) throws SQLException {
throw new SQLFeatureNotSupportedException();
}
}
And jooq-config.xml:
<configuration>
...
<generator>
<database>
<name>org.jooq.util.postgres.PostgresDatabase</name>
<includes>.*</includes>
<excludes>schema_version</excludes>
<inputSchema>public</inputSchema>
<customTypes>
...
<customType>
<name>ARRAY</name>
<type>java.util.Collection</type>
<binding>ru.fabit.contingent.configuration.persistence.PostgresArrayBinding</binding>
</customType>
</customTypes>
<forcedTypes>
...
<forcedType>
<name>ARRAY</name>
<expression>.*_ARRAY</expression>
<types>.*</types>
</forcedType>
</forcedTypes>
</database>
<generate>
<records>true</records>
<interfaces>true</interfaces>
<relations>true</relations>
<validationAnnotations>true</validationAnnotations>
</generate>
<target>
<packageName>ru.fabit.contingent.models.generated</packageName>
<directory>src/main/java/</directory>
</target>
</generator>
</configuration>
SQL:
CREATE TABLE array_tests(string_array varchar(256)[]);
And I had error in generated class:
public final TableField<ArrayTestsRecord, Collection[]> STRING_ARRAY = createField("string_array", org.jooq.impl.DefaultDataType.getDefaultDataType("java.util.Collection").getArrayDataType(), this, "", new PostgresArrayBinding());
no suitable method found for createField(String,DataType,ArrayTests,String,PostgresArrayBinding)
Any ideas?
This is due to a bug in the code generator, which is fixed for jOOQ 3.8: https://github.com/jOOQ/jOOQ/issues/4388
There's no workaround for jOOQ 3.7 or less, I'm afraid, short of manually patching the erroneous generated code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With