From: James Moger Date: Thu, 16 Apr 2015 23:11:30 +0000 (-0400) Subject: Move standard object deserialization into the dialect X-Git-Tag: v1.6.0~11 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=e4952b2465ae4167e24d416b4fc4f6996e2fe229;p=iciql.git Move standard object deserialization into the dialect --- diff --git a/src/main/java/com/iciql/DaoProxy.java b/src/main/java/com/iciql/DaoProxy.java index d27753f..34187c4 100644 --- a/src/main/java/com/iciql/DaoProxy.java +++ b/src/main/java/com/iciql/DaoProxy.java @@ -38,7 +38,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import com.iciql.Iciql.DataTypeAdapter; -import com.iciql.Iciql.TypeAdapter; import com.iciql.util.JdbcUtils; import com.iciql.util.StringUtils; import com.iciql.util.Utils; @@ -175,18 +174,9 @@ final class DaoProxy implements InvocationHandler, Dao { || java.util.Date.class.isAssignableFrom(returnType) || byte[].class.isAssignableFrom(returnType); - // determine the return type adapter, if any - DataTypeAdapter adapter = null; - for (Annotation annotation : method.getAnnotations()) { - if (annotation.annotationType() == TypeAdapter.class) { - TypeAdapter typeAdapter = (TypeAdapter) annotation; - adapter = db.getDialect().getAdapter(typeAdapter.value()); - break; - } else if (annotation.annotationType().isAnnotationPresent(TypeAdapter.class)) { - TypeAdapter typeAdapter = annotation.annotationType().getAnnotation(TypeAdapter.class); - adapter = db.getDialect().getAdapter(typeAdapter.value()); - break; - } + Class> adapter = Utils.getDataTypeAdapter(method.getAnnotations()); + if (adapter == null) { + adapter = Utils.getDataTypeAdapter(returnType.getAnnotations()); } /* @@ -209,17 +199,7 @@ final class DaoProxy implements InvocationHandler, Dao { while (rs.next()) { - Object o = rs.getObject(1); - Object value; - - if (adapter == null) { - // use internal Iciql type conversion - value = Utils.convert(o, returnType); - } else { - // use the type adapter to convert the JDBC object to a domain type - value = adapter.deserialize(o); - } - + Object value = db.getDialect().deserialize(rs, 1, returnType, adapter); objects.add(value); if (!isArray) { @@ -704,7 +684,7 @@ final class DaoProxy implements InvocationHandler, Dao { } // prepare the parameter - parameters[i] = prepareParameter(db, value, typeAdapter); + parameters[i] = db.getDialect().serialize(value, typeAdapter); } @@ -712,32 +692,6 @@ final class DaoProxy implements InvocationHandler, Dao { } - /** - * Prepares a method argument to an sql parameter for transmission to a - * database. - * - * @param db - * @param arg - * @param typeAdapter - * @return a prepared parameter - */ - private Object prepareParameter(Db db, Object arg, Class> typeAdapter) { - - if (typeAdapter != null) { - - // use a type adapter to serialize the method argument - Object o = db.getDialect().serialize(arg, typeAdapter); - return o; - - } else { - - // use the method argument - return arg; - - } - - } - @Override public String toString() { return sql; diff --git a/src/main/java/com/iciql/Query.java b/src/main/java/com/iciql/Query.java index 7c5c985..d52451e 100644 --- a/src/main/java/com/iciql/Query.java +++ b/src/main/java/com/iciql/Query.java @@ -18,8 +18,6 @@ package com.iciql; import java.lang.reflect.Field; -import java.sql.Blob; -import java.sql.Clob; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; @@ -28,6 +26,7 @@ import java.util.HashMap; import java.util.IdentityHashMap; import java.util.List; +import com.iciql.Iciql.DataTypeAdapter; import com.iciql.Iciql.EnumType; import com.iciql.NestedConditions.And; import com.iciql.NestedConditions.Or; @@ -115,7 +114,6 @@ public class Query { return select(true); } - @SuppressWarnings("unchecked") public X selectFirst(Z x) { List list = limit(1).select(x); return list.isEmpty() ? null : list.get(0); @@ -424,18 +422,10 @@ public class Query { appendFromWhere(stat); ResultSet rs = stat.executeQuery(); List result = Utils.newArrayList(); + Class> typeAdapter = Utils.getDataTypeAdapter(x.getClass().getAnnotations()); try { while (rs.next()) { - X value; - Object o = rs.getObject(1); - // Convert CLOB and BLOB now because we close the resultset - if (Clob.class.isAssignableFrom(o.getClass())) { - value = (X) Utils.convert(o, String.class); - } else if (Blob.class.isAssignableFrom(o.getClass())) { - value = (X) Utils.convert(o, byte[].class); - } else { - value = (X) o; - } + X value = (X) db.getDialect().deserialize(rs, 1, x.getClass(), typeAdapter); result.add(value); } } catch (Exception e) { @@ -850,7 +840,8 @@ public class Query { stat.addParameter(y); } else if (col != null) { // object - Object parameter = db.getDialect().serialize(value, col.getFieldDefinition().typeAdapter); + Class> typeAdapter = col.getFieldDefinition().typeAdapter; + Object parameter = db.getDialect().serialize(value, typeAdapter); stat.addParameter(parameter); } else { // primitive diff --git a/src/main/java/com/iciql/SQLDialect.java b/src/main/java/com/iciql/SQLDialect.java index 33c5369..ccc0452 100644 --- a/src/main/java/com/iciql/SQLDialect.java +++ b/src/main/java/com/iciql/SQLDialect.java @@ -18,6 +18,8 @@ package com.iciql; +import java.sql.ResultSet; + import com.iciql.Iciql.DataTypeAdapter; import com.iciql.TableDefinition.IndexDefinition; @@ -54,11 +56,13 @@ public interface SQLDialect { /** * Deserialize the object received from the database into a Java type. * - * @param value + * @param rs + * @param columnIndex + * @param targetType * @param typeAdapter * @return the deserialized object */ - Object deserialize(Object value, Class> typeAdapter); + Object deserialize(ResultSet rs, int columnIndex, Class targetType, Class> typeAdapter); /** * Configure the dialect. diff --git a/src/main/java/com/iciql/SQLDialectDefault.java b/src/main/java/com/iciql/SQLDialectDefault.java index 7c656bd..8547f3c 100644 --- a/src/main/java/com/iciql/SQLDialectDefault.java +++ b/src/main/java/com/iciql/SQLDialectDefault.java @@ -18,8 +18,11 @@ package com.iciql; +import java.sql.Blob; +import java.sql.Clob; import java.sql.Connection; import java.sql.DatabaseMetaData; +import java.sql.ResultSet; import java.sql.SQLException; import java.text.MessageFormat; import java.text.SimpleDateFormat; @@ -476,14 +479,40 @@ public class SQLDialectDefault implements SQLDialect { } @Override - public Object deserialize(Object value, Class> typeAdapter) { + public Object deserialize(ResultSet rs, int columnIndex, Class targetType, Class> typeAdapter) { if (typeAdapter == null) { - // pass-through + // standard object deserialization + Object value = null; + try { + // use internal Iciql type conversion + Object o = rs.getObject(columnIndex); + if (Clob.class.isAssignableFrom(o.getClass())) { + value = Utils.convert(o, String.class); + } else if (Blob.class.isAssignableFrom(o.getClass())) { + value = Utils.convert(o, byte[].class); + } else { + value = Utils.convert(o, targetType); + } + } catch (SQLException e) { + throw new IciqlException(e, "Can not convert the value at column {0} to {1}", + columnIndex, targetType.getName()); + } + return value; - } + } else { + // custom object deserialization with a DataTypeAdapter + DataTypeAdapter dta = getAdapter(typeAdapter); + Object object = null; + try { + object = rs.getObject(columnIndex); + } catch (SQLException e) { + throw new IciqlException(e, "Can not convert the value at column {0} to {1}", + columnIndex, targetType.getName()); + } - DataTypeAdapter dta = getAdapter(typeAdapter); - return dta.deserialize(value); + Object value = dta.deserialize(object); + return value; + } } @Override diff --git a/src/main/java/com/iciql/TableDefinition.java b/src/main/java/com/iciql/TableDefinition.java index e07cee6..8248f18 100644 --- a/src/main/java/com/iciql/TableDefinition.java +++ b/src/main/java/com/iciql/TableDefinition.java @@ -42,7 +42,6 @@ import com.iciql.Iciql.IQContraintForeignKey; import com.iciql.Iciql.IQContraintUnique; import com.iciql.Iciql.IQContraintsForeignKey; import com.iciql.Iciql.IQContraintsUnique; -import com.iciql.Iciql.IQEnum; import com.iciql.Iciql.IQIgnore; import com.iciql.Iciql.IQIndex; import com.iciql.Iciql.IQIndexes; @@ -134,25 +133,17 @@ public class TableDefinition { private Object initWithNewObject(Object obj) { Object o = Utils.newObject(field.getType()); - setValue(null, obj, o); + setValue(obj, o); return o; } - private void setValue(SQLDialect dialect, Object obj, Object o) { + private void setValue(Object obj, Object o) { try { if (!field.isAccessible()) { field.setAccessible(true); } - Class targetType = field.getType(); - if (targetType.isEnum()) { - o = Utils.convertEnum(o, targetType, enumType); - } else if (dialect != null && typeAdapter != null) { - o = dialect.deserialize(o, typeAdapter); - } else { - o = Utils.convert(o, targetType); - } - if (targetType.isPrimitive() && o == null) { + if (field.getType().isPrimitive() && o == null) { // do not attempt to set a primitive to null return; } @@ -165,14 +156,6 @@ public class TableDefinition { } } - private Object read(ResultSet rs, int columnIndex) { - try { - return rs.getObject(columnIndex); - } catch (SQLException e) { - throw new IciqlException(e); - } - } - @Override public int hashCode() { return columnName.hashCode(); @@ -457,32 +440,14 @@ public class TableDefinition { int scale = 0; boolean trim = false; boolean nullable = !f.getType().isPrimitive(); - EnumType enumType = null; - Class enumTypeClass = null; String defaultValue = ""; String constraint = ""; String dataType = null; Class> typeAdapter = null; // configure Java -> SQL enum mapping - if (f.getType().isEnum()) { - enumType = EnumType.DEFAULT_TYPE; - if (f.getType().isAnnotationPresent(IQEnum.class)) { - // enum definition is annotated for all instances - IQEnum iqenum = f.getType().getAnnotation(IQEnum.class); - enumType = iqenum.value(); - } - if (f.isAnnotationPresent(IQEnum.class)) { - // this instance of the enum is annotated - IQEnum iqenum = f.getAnnotation(IQEnum.class); - enumType = iqenum.value(); - } - - if (EnumId.class.isAssignableFrom(f.getType())) { - // custom enumid mapping - enumTypeClass = ((EnumId) f.getType().getEnumConstants()[0]).enumIdClass(); - } - } + EnumType enumType = Utils.getEnumType(f); + Class enumTypeClass = Utils.getEnumTypeClass(f); // try using default object try { @@ -1201,9 +1166,20 @@ public class TableDefinition { void readRow(SQLDialect dialect, Object item, ResultSet rs, int[] columns) { for (int i = 0; i < fields.size(); i++) { FieldDefinition def = fields.get(i); - int index = columns[i]; - Object o = def.read(rs, index); - def.setValue(dialect, item, o); + Class targetType = def.field.getType(); + Object o; + if (targetType.isEnum()) { + Object obj; + try { + obj = rs.getObject(columns[i]); + } catch (SQLException e) { + throw new IciqlException(e); + } + o = Utils.convertEnum(obj, targetType, def.enumType); + } else { + o = dialect.deserialize(rs, columns[i], targetType, def.typeAdapter); + } + def.setValue(item, o); } } diff --git a/src/main/java/com/iciql/util/Utils.java b/src/main/java/com/iciql/util/Utils.java index bf66092..f4dbb81 100644 --- a/src/main/java/com/iciql/util/Utils.java +++ b/src/main/java/com/iciql/util/Utils.java @@ -24,6 +24,7 @@ import java.io.Reader; import java.io.StringWriter; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; +import java.lang.reflect.Field; import java.math.BigDecimal; import java.math.BigInteger; import java.sql.Blob; @@ -44,6 +45,7 @@ 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.IQEnum; import com.iciql.Iciql.TypeAdapter; import com.iciql.IciqlException; @@ -352,6 +354,59 @@ public class Utils { throw new IciqlException("Can not convert the value {0} from {1} to {2}", o, currentType, targetType); } + /** + * Identify the EnumType for the field. + * + * @param f + * @return null or the EnumType + */ + public static EnumType getEnumType(Field f) { + EnumType enumType = null; + if (f.getType().isEnum()) { + enumType = EnumType.DEFAULT_TYPE; + if (f.getType().isAnnotationPresent(IQEnum.class)) { + // enum definition is annotated for all instances + IQEnum iqenum = f.getType().getAnnotation(IQEnum.class); + enumType = iqenum.value(); + } + if (f.isAnnotationPresent(IQEnum.class)) { + // this instance of the enum is annotated + IQEnum iqenum = f.getAnnotation(IQEnum.class); + enumType = iqenum.value(); + } + } + return enumType; + } + + /** + * Identify the EnumType from the annotations. + * + * @param annotations + * @return null or the EnumType + */ + public static EnumType getEnumType(Annotation [] annotations) { + EnumType enumType = null; + if (annotations != null) { + for (Annotation annotation : annotations) { + if (annotation instanceof IQEnum) { + enumType = ((IQEnum) annotation).value(); + break; + } + } + } + return enumType; + } + + public static Class getEnumTypeClass(Field f) { + if (f.getType().isEnum()) { + if (EnumId.class.isAssignableFrom(f.getType())) { + // custom enumid mapping + return ((EnumId) f.getType().getEnumConstants()[0]).enumIdClass(); + } + } + return null; + } + public static Object convertEnum(Enum o, EnumType type) { if (o == null) { return null; @@ -540,7 +595,7 @@ public class Utils { * Identify the data type adapter class in the annotations. * * @param annotations - * @return null or the dtaa type adapter class + * @return null or the data type adapter class */ public static Class> getDataTypeAdapter(Annotation [] annotations) { Class> typeAdapter = null;