summaryrefslogtreecommitdiffstats
path: root/src/site/dta.mkd
blob: 70fc25e9e8efa394e0cb8dfe9b608df9a1b194c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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
## 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> {

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

### 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>