Aktuelle jOOQ-Versionen
jOOQ bietet native Unterstützung für JSON
und JSONB
Datentypen, sodass Sie nichts Besonderes tun müssen.
Historische Antwort
Seit jOOQ 3.5 können Sie Ihre eigenen benutzerdefinierten Datentypbindungen beim Codegenerator registrieren, wie hier dokumentiert:
http://www.jooq.org/doc/latest/manual/code-generation/custom-data-type-bindings
Im Gegensatz zu einem Converter
, eine Binding
bestimmt, wie Ihr Datentyp auf JDBC-Ebene innerhalb von jOOQ behandelt wird, ohne dass jOOQ etwas über Ihre Implementierung weiß. Das heißt, Sie definieren nicht nur, wie zwischen <T>
konvertiert werden soll und <U>
Typen (T
=Datenbanktyp, U
=Benutzertyp), aber Sie können auch definieren, wie solche Typen sind:
- Als SQL gerendert
- An PreparedStatements gebunden
- An SQLOutput gebunden
- In CallableStatements als OUT-Parameter registriert
- Aus ResultSets abgerufen
- Von SQLInput abgerufen
- Von CallableStatements als OUT-Parameter abgerufen
Ein Beispiel für Binding
zur Verwendung mit Jackson zur Erzeugung von JsonNode
Typen ist hier angegeben:
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();
}
}
Und der Converter
die oben verwendet wird, kann hier eingesehen werden:
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;
}
}
Sie können nun die obige Bindung über die Codegenerator-Konfiguration registrieren:
<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>