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
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<T></td><td><T></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<T></td><td><T></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<T></td><td><T></td><td>JSON</td><td>
Uses Google Gson to (de)serialize your object as JSON</td></tr>
<tr><td>com.iciql.adapter.postgresql.JsonbObjectAdapter<T></td><td><T></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>
|