aboutsummaryrefslogtreecommitdiffstats
path: root/weaver/ajsrc
ModeNameSize
d---------org / aspectj / weaver34logstatsplain
> 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
## Data Type Adapters

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](http://www.postgresql.org/docs/9.4/static/datatype-json.html) in 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.

---JAVA---
@IQTable
public class Invoices {
    
    @IQColumn(primaryKey = true, autoIncrement = true)
    public long _id;
    
    @IQColumn
    Date received;
    
    @IQColumn
    @TypeAdapter(InvoiceAdapterImpl.class)
    Invoice invoice;
}
---JAVA---

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

---JAVA---
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;
    }
}
---JAVA---

Here you can see how the *InvoiceTypeAdapter* defines a [Postgres JSONB data type](http://www.postgresql.org/docs/9.4/static/datatype-json.html) and automatically handles JSON (de)serialization with [Google Gson](https://code.google.com/p/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.

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

### Included Data Type Adapters

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

<table class="table">
<tr><td colspan="4"><b>Common Type Adapters</b></tr>
<tr><td><i>Adapter</i></td><td><i>Java</i></td><td><i>SQL</i></td><td><i>Description</i></td></tr>

<tr><td>com.iciql.adapter.JavaSerializationTypeAdapter</td><td>Object</td><td>BLOB</td><td>Uses Java serialization to (de)serialize your object</td></tr>

<tr><td>com.iciql.adapter.GsonTypeAdapter&lt;T&gt;</td><td>&lt;T&gt;</td><td>TEXT</td><td>
Uses Google Gson to (de)serialize your object as JSON</td></tr>

<tr><td>com.iciql.adapter.XStreamTypeAdapter</td><td>Object</td><td>TEXT</td><td>
Uses XStream to (de)serialize your object as XML</td></tr>

<tr><td>com.iciql.adapter.SnakeYamlTypeAdapter&lt;T&gt;</td><td>&lt;T&gt;</td><td>TEXT</td><td>
Uses SnakeYaml to (de)serialize your object as YAML</td></tr>

<tr><td colspan="4"><b>PostgreSQL Type Adapters</b></tr>
<tr><td><i>Object Adapters</i></td><td><i>Java</i></td><td><i>SQL</i></td><td><i>Description</i></td></tr>

<tr><td>com.iciql.adapter.postgresql.JsonObjectAdapter&lt;T&gt;</td><td>&lt;T&gt;</td><td>JSON</td><td>
Uses Google Gson to (de)serialize your object as JSON</td></tr>

<tr><td>com.iciql.adapter.postgresql.JsonbObjectAdapter&lt;T&gt;</td><td>&lt;T&gt;</td><td>JSONB</td><td>
Uses Google Gson to (de)serialize your object as JSONB</td></tr>

<tr><td>com.iciql.adapter.postgresql.XmlObjectAdapter</td><td>Object</td><td>XML</td><td>
Uses XStream to (de)serialize your object as XML</td></tr>

<tr><td colspan="4"><i>String Adapters</i></td></tr>

<tr><td>com.iciql.adapter.postgresql.JsonStringAdapter</td><td>String</td><td>JSON</td><td>
Maps the JSON data type to a java.lang.String</td></tr>

<tr><td>com.iciql.adapter.postgresql.JsonbStringAdapter</td><td>String</td><td>JSONB</td><td>
Maps the JSONB data type to a java.lang.String</td></tr>

<tr><td>com.iciql.adapter.postgresql.XmlStringAdapter</td><td>String</td><td>XML</td><td>
Maps the XML data type to a java.lang.String</td></tr>

</table>