ソースを参照

Move standard object deserialization into the dialect

tags/v1.6.0
James Moger 9年前
コミット
e4952b2465

+ 5
- 51
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<X extends Dao> 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<? extends DataTypeAdapter<?>> adapter = Utils.getDataTypeAdapter(method.getAnnotations());
if (adapter == null) {
adapter = Utils.getDataTypeAdapter(returnType.getAnnotations());
}

/*
@@ -209,17 +199,7 @@ final class DaoProxy<X extends Dao> 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<X extends Dao> 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<X extends Dao> 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<? extends DataTypeAdapter<?>> 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;

+ 5
- 14
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<T> {
return select(true);
}
@SuppressWarnings("unchecked")
public <X, Z> X selectFirst(Z x) {
List<X> list = limit(1).select(x);
return list.isEmpty() ? null : list.get(0);
@@ -424,18 +422,10 @@ public class Query<T> {
appendFromWhere(stat);
ResultSet rs = stat.executeQuery();
List<X> result = Utils.newArrayList();
Class<? extends DataTypeAdapter<?>> 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<T> {
stat.addParameter(y);
} else if (col != null) {
// object
Object parameter = db.getDialect().serialize(value, col.getFieldDefinition().typeAdapter);
Class<? extends DataTypeAdapter<?>> typeAdapter = col.getFieldDefinition().typeAdapter;
Object parameter = db.getDialect().serialize(value, typeAdapter);
stat.addParameter(parameter);
} else {
// primitive

+ 6
- 2
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<? extends DataTypeAdapter<?>> typeAdapter);
Object deserialize(ResultSet rs, int columnIndex, Class<?> targetType, Class<? extends DataTypeAdapter<?>> typeAdapter);

/**
* Configure the dialect.

+ 34
- 5
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<? extends DataTypeAdapter<?>> typeAdapter) {
public Object deserialize(ResultSet rs, int columnIndex, Class<?> targetType, Class<? extends DataTypeAdapter<?>> 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

+ 19
- 43
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<T> {

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<T> {
}
}

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<T> {
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<? extends DataTypeAdapter<?>> 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<T> {
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);
}
}


+ 56
- 1
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<? extends DataTypeAdapter<?>> getDataTypeAdapter(Annotation [] annotations) {
Class<? extends DataTypeAdapter<?>> typeAdapter = null;

読み込み中…
キャンセル
保存