Versiones actuales de jOOQ
jOOQ tiene soporte nativo para JSON
y JSONB
tipos de datos, por lo que no tiene que hacer nada específico.
Respuesta histórica
Desde jOOQ 3.5, puede registrar sus propios enlaces de tipo de datos personalizados al generador de código como se documenta aquí:
http://www.jooq.org/doc/latest/manual/code-generation/custom-data-type-bindings
A diferencia de un Converter
, un Binding
dicta cómo se maneja su tipo de datos en el nivel JDBC dentro de jOOQ, sin que jOOQ conozca su implementación. Es decir, no solo definirá cómo convertir entre <T>
y <U>
tipos (T
=tipo de base de datos, U
=tipo de usuario), pero también podrá definir cómo son dichos tipos:
- Representado como SQL
- Enlazado a declaraciones preparadas
- Enlazado a SQLOutput
- Registrado en CallableStatements como parámetros OUT
- Obtenido de ResultSets
- Obtenido de SQLInput
- Obtenido de CallableStatements como parámetros OUT
Un ejemplo de Binding
para usar con Jackson para producir JsonNode
tipos se da aquí:
public class PostgresJSONJacksonJsonNodeBinding
implements Binding<Object, JsonNode> {
@Override
public Converter<Object, JsonNode> converter() {
return new PostgresJSONJacksonJsonNodeConverter();
}
@Override
public void sql(BindingSQLContext<JsonNode> ctx) throws SQLException {
// This ::json cast is explicitly needed by PostgreSQL:
ctx.render().visit(DSL.val(ctx.convert(converter()).value())).sql("::json");
}
@Override
public void register(BindingRegisterContext<JsonNode> ctx) throws SQLException {
ctx.statement().registerOutParameter(ctx.index(), Types.VARCHAR);
}
@Override
public void set(BindingSetStatementContext<JsonNode> ctx) throws SQLException {
ctx.statement().setString(
ctx.index(),
Objects.toString(ctx.convert(converter()).value()));
}
@Override
public void get(BindingGetResultSetContext<JsonNode> ctx) throws SQLException {
ctx.convert(converter()).value(ctx.resultSet().getString(ctx.index()));
}
@Override
public void get(BindingGetStatementContext<JsonNode> ctx) throws SQLException {
ctx.convert(converter()).value(ctx.statement().getString(ctx.index()));
}
// The below methods aren't needed in PostgreSQL:
@Override
public void set(BindingSetSQLOutputContext<JsonNode> ctx) throws SQLException {
throw new SQLFeatureNotSupportedException();
}
@Override
public void get(BindingGetSQLInputContext<JsonNode> ctx) throws SQLException {
throw new SQLFeatureNotSupportedException();
}
}
Y el Converter
que se usa arriba se puede ver aquí:
public class PostgresJSONJacksonJsonNodeConverter
implements Converter<Object, JsonNode> {
@Override
public JsonNode from(Object t) {
try {
return t == null
? NullNode.instance
: new ObjectMapper().readTree(t + "");
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public Object to(JsonNode u) {
try {
return u == null || u.equals(NullNode.instance)
? null
: new ObjectMapper().writeValueAsString(u);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public Class<Object> fromType() {
return Object.class;
}
@Override
public Class<JsonNode> toType() {
return JsonNode.class;
}
}
Ahora puede registrar el enlace anterior a través de la configuración del generador de código:
<customType>
<name>com.example.PostgresJSONJacksonJsonNodeBinding</name>
<type>com.fasterxml.jackson.databind.JsonNode</type>
<binding>com.example.PostgresJSONJacksonJsonNodeBinding</binding>
</customType>
<forcedType>
<name>com.example.PostgresJSONJacksonJsonNodeBinding</name>
<expression>my_schema\.table\.json_field</expression>
</forcedType>