Data Type Adapters (DTAs)

Data type adapters allow you to extend Iciql’s support for field data types.

For example, you might want to take advantage of the Postgres JSON/JSONB support since 9.3/9.4 but instead of directly handling JSON text documents you might want to represent that JSON as a domain object and serialize/deserialize to JSON only when executing an SQL operation.

Data type adapters give you this flexibility.

NOTE: Data type adapters are reused within a Db instance and are not inherently thread-safe. You must handle thread-safety on your own, if it is an issue.

An example#

Consider the following model class.

@IQTable
public class Invoices {

    @IQColumn(primaryKey = true, autoIncrement = true)
    public long _id;

    @IQColumn
    Date received;

    @IQColumn
    @TypeAdapter(InvoiceAdapterImpl.class)
    Invoice invoice;
}

This is a really simple table with three columns, but the third column uses a type adapter to map our invoice object field to an SQL type. You can use the @TypeAdapter annotation either on the field definition or on the class definition of your domain model.

Let’s take a look at InvoiceAdapterImpl.

public class InvoiceAdapterImpl implements DataTypeAdapter<Invoice> {

    Mode mode;

    @Override
    public void setMode(Mode mode) {
        this.mode = mode;
    }

    @Override
    public String getDataType() {
        return "jsonb";
    }

    @Override
    public Class<Invoice> getJavaType() {
        return Invoice.class;
    }

    Gson gson() {
        return new GsonBuilder().create();
    }

    @Override
    public Object serialize(Invoice value) {
        String json = gson().toJson(value);
        PGobject pg = new PGobject();
        pg.setType(getDataType());
        try {
            pg.setValue(json);
        } catch (SQLException e) {
            // ignore, never thrown
        }
        return pg;
    }

    @Override
    public Invoice deserialize(Object value) {

        // the incoming object is always represented as a string
        final String json = value.toString();
        final Invoice invoice = gson().fromJson(json, getJavaType());

        return invoice;
    }
}

Here you can see how the InvoiceTypeAdapter defines a Postgres JSONB data type and automatically handles JSON (de)serialization with Google Gson so that the database gets the content in a form that it requires but we can continue to work with objects in Java.

Runtime Mode#

Data type adapters can respond to the Iciql runtime mode (DEV, TEST, or PROD) allowing them to change their behavior. This is useful for targetting a data type that might be available in your production database but may not be available in your development or testing database.

Custom annotations#

It is a little verbose to repeat @TypeAdapter(InvoiceAdapterImpl.class) everywhere you want to use your adapter.

To simplify this, you can implement your own annotation which specifies your type adapter.

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER })
@TypeAdapter(InvoiceAdapterImpl.class)
public @interface InvoiceAdapter { }

Included Data Type Adapters#

The following adapters are included in Iciql. They may require an optional dependency such as Gson, XStream, or SnakeYaml.

Common Type Adapters
AdapterJavaSQLDescription
com.iciql.adapter.JavaSerializationTypeAdapterObjectBLOBUses Java serialization to (de)serialize your object
com.iciql.adapter.GsonTypeAdapter<T><T>TEXT Uses Google Gson to (de)serialize your object as JSON
com.iciql.adapter.XStreamTypeAdapterObjectTEXT Uses XStream to (de)serialize your object as XML
com.iciql.adapter.SnakeYamlTypeAdapter<T><T>TEXT Uses SnakeYaml to (de)serialize your object as YAML
PostgreSQL Type Adapters
Object AdaptersJavaSQLDescription
com.iciql.adapter.postgresql.JsonObjectAdapter<T><T>JSON Uses Google Gson to (de)serialize your object as JSON
com.iciql.adapter.postgresql.JsonbObjectAdapter<T><T>JSONB Uses Google Gson to (de)serialize your object as JSONB
com.iciql.adapter.postgresql.XmlObjectAdapterObjectXML Uses XStream to (de)serialize your object as XML
String Adapters
com.iciql.adapter.postgresql.JsonStringAdapterStringJSON Maps the JSON data type to a java.lang.String
com.iciql.adapter.postgresql.JsonbStringAdapterStringJSONB Maps the JSONB data type to a java.lang.String
com.iciql.adapter.postgresql.XmlStringAdapterStringXML Maps the XML data type to a java.lang.String