aboutsummaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/com/iciql/Iciql.java46
-rw-r--r--src/main/java/com/iciql/SQLDialectPostgreSQL.java33
-rw-r--r--src/main/java/com/iciql/TableDefinition.java18
-rw-r--r--src/main/java/com/iciql/util/Utils.java23
4 files changed, 78 insertions, 42 deletions
diff --git a/src/main/java/com/iciql/Iciql.java b/src/main/java/com/iciql/Iciql.java
index 05cceeb..524faa8 100644
--- a/src/main/java/com/iciql/Iciql.java
+++ b/src/main/java/com/iciql/Iciql.java
@@ -657,14 +657,6 @@ public interface Iciql {
*/
String defaultValue() default "";
- /**
- * Allows specifying a custom data type adapter.
- * <p>
- * For example, you might use this option to map a Postgres JSON column.
- * </p>
- */
- Class<? extends DataTypeAdapter<?>> typeAdapter() default StandardJDBCTypeAdapter.class;
-
}
/**
@@ -741,6 +733,17 @@ public interface Iciql {
void defineIQ();
/**
+ * Specify a custom type adapter for a method return type, a class field, or a method
+ * parameter. Type adapters allow you to transform content received from or inserted into
+ * a database field.
+ */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER })
+ public @interface TypeAdapter {
+ Class<? extends DataTypeAdapter<?>> value();
+ }
+
+ /**
* Interface to allow implementations of custom data type adapters for supporting
* database-specific data types, like the Postgres 'json' or 'xml' types,
* or for supporting other object serialization schemes.
@@ -782,31 +785,4 @@ public interface Iciql {
}
- /**
- * The standard type adapter allows iciql to use it's internal utility convert functions
- * to handle the standard JDBC types.
- */
- public final static class StandardJDBCTypeAdapter implements DataTypeAdapter<Object> {
-
- @Override
- public String getDataType() {
- throw new RuntimeException("This adapter is for all standard JDBC types.");
- }
-
- @Override
- public Class<Object> getJavaType() {
- throw new RuntimeException("This adapter is for all standard JDBC types.");
- }
-
- @Override
- public Object serialize(Object value) {
- return value;
- }
-
- @Override
- public Object deserialize(Object value) {
- return value;
- }
-
- }
}
diff --git a/src/main/java/com/iciql/SQLDialectPostgreSQL.java b/src/main/java/com/iciql/SQLDialectPostgreSQL.java
index b5ac5c3..f10017c 100644
--- a/src/main/java/com/iciql/SQLDialectPostgreSQL.java
+++ b/src/main/java/com/iciql/SQLDialectPostgreSQL.java
@@ -140,6 +140,39 @@ public class SQLDialectPostgreSQL extends SQLDialectDefault {
}
/**
+ * Handles transforming raw strings to/from the Postgres JSONB data type.
+ */
+ public class JsonbStringAdapter implements DataTypeAdapter<String> {
+
+ @Override
+ public String getDataType() {
+ return "jsonb";
+ }
+
+ @Override
+ public Class<String> getJavaType() {
+ return String.class;
+ }
+
+ @Override
+ public Object serialize(String value) {
+ PGobject pg = new PGobject();
+ pg.setType(getDataType());
+ try {
+ pg.setValue(value);
+ } catch (SQLException e) {
+ // not thrown on base PGobject
+ }
+ return pg;
+ }
+
+ @Override
+ public String deserialize(Object value) {
+ return value.toString();
+ }
+ }
+
+ /**
* Handles transforming raw strings to/from the Postgres XML data type.
*/
public class XmlStringAdapter implements DataTypeAdapter<String> {
diff --git a/src/main/java/com/iciql/TableDefinition.java b/src/main/java/com/iciql/TableDefinition.java
index fc83d29..e4fff87 100644
--- a/src/main/java/com/iciql/TableDefinition.java
+++ b/src/main/java/com/iciql/TableDefinition.java
@@ -51,7 +51,6 @@ import com.iciql.Iciql.IQTable;
import com.iciql.Iciql.IQVersion;
import com.iciql.Iciql.IQView;
import com.iciql.Iciql.IndexType;
-import com.iciql.Iciql.StandardJDBCTypeAdapter;
import com.iciql.util.IciqlLogger;
import com.iciql.util.StatementBuilder;
import com.iciql.util.StringUtils;
@@ -525,6 +524,17 @@ public class TableDefinition<T> {
throw new IciqlException(e, "failed to get default object for {0}", columnName);
}
+ // identify the type adapter
+ typeAdapter = Utils.getDataTypeAdapter(f.getAnnotations());
+ if (typeAdapter == null) {
+ typeAdapter = Utils.getDataTypeAdapter(f.getType().getAnnotations());
+ }
+
+ if (typeAdapter != null) {
+ DataTypeAdapter<?> dtt = db.getDialect().getAdapter(typeAdapter);
+ dataType = dtt.getDataType();
+ }
+
boolean hasAnnotation = f.isAnnotationPresent(IQColumn.class);
if (hasAnnotation) {
IQColumn col = f.getAnnotation(IQColumn.class);
@@ -538,12 +548,6 @@ public class TableDefinition<T> {
trim = col.trim();
nullable = col.nullable();
- if (col.typeAdapter() != null && col.typeAdapter() != StandardJDBCTypeAdapter.class) {
- typeAdapter = col.typeAdapter();
- DataTypeAdapter<?> dtt = db.getDialect().getAdapter(col.typeAdapter());
- dataType = dtt.getDataType();
- }
-
// annotation overrides
if (!StringUtils.isNullOrEmpty(col.defaultValue())) {
defaultValue = col.defaultValue();
diff --git a/src/main/java/com/iciql/util/Utils.java b/src/main/java/com/iciql/util/Utils.java
index 346c6d7..bf66092 100644
--- a/src/main/java/com/iciql/util/Utils.java
+++ b/src/main/java/com/iciql/util/Utils.java
@@ -22,6 +22,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringWriter;
+import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.math.BigDecimal;
import java.math.BigInteger;
@@ -40,8 +41,10 @@ import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
+import com.iciql.Iciql.DataTypeAdapter;
import com.iciql.Iciql.EnumId;
import com.iciql.Iciql.EnumType;
+import com.iciql.Iciql.TypeAdapter;
import com.iciql.IciqlException;
/**
@@ -532,4 +535,24 @@ public class Utils {
in.close();
}
}
+
+ /**
+ * Identify the data type adapter class in the annotations.
+ *
+ * @param annotations
+ * @return null or the dtaa type adapter class
+ */
+ public static Class<? extends DataTypeAdapter<?>> getDataTypeAdapter(Annotation [] annotations) {
+ Class<? extends DataTypeAdapter<?>> typeAdapter = null;
+ if (annotations != null) {
+ for (Annotation annotation : annotations) {
+ if (annotation instanceof TypeAdapter) {
+ typeAdapter = ((TypeAdapter) annotation).value();
+ } else if (annotation.annotationType().isAnnotationPresent(TypeAdapter.class)) {
+ typeAdapter = annotation.annotationType().getAnnotation(TypeAdapter.class).value();
+ }
+ }
+ }
+ return typeAdapter;
+ }
}