description: 'a model-based database access wrapper for JDBC' | description: 'a model-based database access wrapper for JDBC' | ||||
groupId: com.iciql | groupId: com.iciql | ||||
artifactId: iciql | artifactId: iciql | ||||
version: 1.7.0-SNAPSHOT | |||||
version: 1.6.2-SNAPSHOT | |||||
packaging: jar+zip | packaging: jar+zip | ||||
inceptionYear: 2011 | inceptionYear: 2011 | ||||
html: ~ | html: ~ | ||||
text: ~ | text: ~ | ||||
security: ~ | security: ~ | ||||
fixes: ~ | |||||
fixes: | |||||
- Reverted change which keyed DataTypeAdapters by the target Java type | |||||
changes: ~ | changes: ~ | ||||
additions: ~ | additions: ~ | ||||
dependencyChanges: ~ | dependencyChanges: ~ | ||||
fixes: | fixes: | ||||
- Fix column inheritance from superclasses (pr-14) | - Fix column inheritance from superclasses (pr-14) | ||||
- Use webapp classloader rather than global classloader (pr-12) | - Use webapp classloader rather than global classloader (pr-12) | ||||
- Fix deserialization of null values | |||||
changes: | changes: | ||||
- Improve SQLite dialect based on upstream JDBC improvements | - Improve SQLite dialect based on upstream JDBC improvements | ||||
- Key DataTypeAdapters by target Java type | |||||
- Drop precision and length from SQL->Java type determination | |||||
- Improve readability of the generated performance benchmark table | |||||
- Added Derby TCP benchmark test | |||||
additions: ~ | additions: ~ | ||||
dependencyChanges: | dependencyChanges: | ||||
- SQLite 3.8.10 | - SQLite 3.8.10 | ||||
fixes: | fixes: | ||||
- Fix column inheritance from superclasses (pr-14) | - Fix column inheritance from superclasses (pr-14) | ||||
- Use webapp classloader rather than global classloader (pr-12) | - Use webapp classloader rather than global classloader (pr-12) | ||||
- Fix deserialization of null values | |||||
changes: | changes: | ||||
- Improve SQLite dialect based on upstream JDBC improvements | - Improve SQLite dialect based on upstream JDBC improvements | ||||
- Key DataTypeAdapters by target Java type | |||||
- Drop precision and length from SQL->Java type determination | |||||
- Improve readability of the generated performance benchmark table | |||||
- Added Derby TCP benchmark test | |||||
additions: ~ | additions: ~ | ||||
dependencyChanges: | dependencyChanges: | ||||
- SQLite 3.8.10 | - SQLite 3.8.10 |
} else { | } else { | ||||
// query of (array of) standard Java type or a DataTypeAdapter type | // query of (array of) standard Java type or a DataTypeAdapter type | ||||
if (adapter != null) { | |||||
DataTypeAdapter<?> dta = Utils.newObject(adapter); | |||||
db.getDialect().registerAdapter(dta); | |||||
} | |||||
objects = Utils.newArrayList(); | objects = Utils.newArrayList(); | ||||
ResultSet rs = db.executeQuery(preparedSql.sql, preparedSql.parameters); | ResultSet rs = db.executeQuery(preparedSql.sql, preparedSql.parameters); | ||||
try { | try { | ||||
while (rs.next()) { | while (rs.next()) { | ||||
Object value = db.getDialect().deserialize(rs, 1, returnType); | |||||
Object value = db.getDialect().deserialize(rs, 1, returnType, adapter); | |||||
objects.add(value); | objects.add(value); | ||||
if (!isArray) { | if (!isArray) { | ||||
typeAdapter = Utils.getDataTypeAdapter(methodArg.getClass().getAnnotations()); | typeAdapter = Utils.getDataTypeAdapter(methodArg.getClass().getAnnotations()); | ||||
} | } | ||||
if (typeAdapter != null) { | |||||
DataTypeAdapter<?> dta = Utils.newObject(typeAdapter); | |||||
db.getDialect().registerAdapter(dta); | |||||
} | |||||
// prepare the parameter | // prepare the parameter | ||||
parameters[i] = db.getDialect().serialize(value); | |||||
parameters[i] = db.getDialect().serialize(value, typeAdapter); | |||||
} | } | ||||
void registerAdapter(DataTypeAdapter<?> typeAdapter); | void registerAdapter(DataTypeAdapter<?> typeAdapter); | ||||
/** | /** | ||||
* Returns the registered instance of the type adapter for the specified object class. | |||||
* Returns the registered instance of the type adapter. | |||||
* | * | ||||
* @param objectClass | |||||
* @param typeAdapter | |||||
* @return the type adapter instance | * @return the type adapter instance | ||||
*/ | */ | ||||
DataTypeAdapter<?> getAdapter(Class<?> objectClass); | |||||
DataTypeAdapter<?> getAdapter(Class<? extends DataTypeAdapter<?>> typeAdapter); | |||||
/** | /** | ||||
* Serialize the Java object into a type or format that the database will accept. | * Serialize the Java object into a type or format that the database will accept. | ||||
* | * | ||||
* @param value | * @param value | ||||
* @param typeAdapter | |||||
* @return the serialized object | * @return the serialized object | ||||
*/ | */ | ||||
<T> Object serialize(T value); | |||||
<T> Object serialize(T value, Class<? extends DataTypeAdapter<?>> typeAdapter); | |||||
/** | /** | ||||
* Deserialize the object received from the database into a Java type. | * Deserialize the object received from the database into a Java type. | ||||
* @param rs | * @param rs | ||||
* @param columnIndex | * @param columnIndex | ||||
* @param targetType | * @param targetType | ||||
* @param typeAdapter | |||||
* @return the deserialized object | * @return the deserialized object | ||||
*/ | */ | ||||
Object deserialize(ResultSet rs, int columnIndex, Class<?> targetType); | |||||
Object deserialize(ResultSet rs, int columnIndex, Class<?> targetType, Class<? extends DataTypeAdapter<?>> typeAdapter); | |||||
/** | /** | ||||
* Configure the dialect. | * Configure the dialect. |
String databaseName; | String databaseName; | ||||
String productVersion; | String productVersion; | ||||
Mode mode; | Mode mode; | ||||
Map<Class<?>, DataTypeAdapter<?>> typeAdapters; | |||||
Map<Class<? extends DataTypeAdapter<?>>, DataTypeAdapter<?>> typeAdapters; | |||||
public SQLDialectDefault() { | public SQLDialectDefault() { | ||||
typeAdapters = new ConcurrentHashMap<Class<?>, DataTypeAdapter<?>>(); | |||||
typeAdapters = new ConcurrentHashMap<Class<? extends DataTypeAdapter<?>>, DataTypeAdapter<?>>(); | |||||
} | } | ||||
@Override | @Override | ||||
buff.appendExceptFirst(", "); | buff.appendExceptFirst(", "); | ||||
buff.append('?'); | buff.append('?'); | ||||
Object value = def.getValue(obj, field); | Object value = def.getValue(obj, field); | ||||
Object parameter = serialize(value); | |||||
Object parameter = serialize(value, field.typeAdapter); | |||||
stat.addParameter(parameter); | stat.addParameter(parameter); | ||||
} | } | ||||
buff.append(" FROM "); | buff.append(" FROM "); | ||||
buff.appendExceptFirst(" AND "); | buff.appendExceptFirst(" AND "); | ||||
buff.append(MessageFormat.format("{0} = ?", prepareColumnName(field.columnName))); | buff.append(MessageFormat.format("{0} = ?", prepareColumnName(field.columnName))); | ||||
Object value = def.getValue(obj, field); | Object value = def.getValue(obj, field); | ||||
Object parameter = serialize(value); | |||||
Object parameter = serialize(value, field.typeAdapter); | |||||
stat.addParameter(parameter); | stat.addParameter(parameter); | ||||
} | } | ||||
} | } | ||||
@Override | @Override | ||||
public void registerAdapter(DataTypeAdapter<?> typeAdapter) { | public void registerAdapter(DataTypeAdapter<?> typeAdapter) { | ||||
typeAdapters.put(typeAdapter.getJavaType(), typeAdapter); | |||||
typeAdapters.put((Class<? extends DataTypeAdapter<?>>) typeAdapter.getClass(), typeAdapter); | |||||
} | } | ||||
@Override | @Override | ||||
public DataTypeAdapter<?> getAdapter(Class<?> objectClass) { | |||||
DataTypeAdapter<?> dta = typeAdapters.get(objectClass); | |||||
if (dta != null) { | |||||
dta.setMode(mode); | |||||
public DataTypeAdapter<?> getAdapter(Class<? extends DataTypeAdapter<?>> typeAdapter) { | |||||
DataTypeAdapter<?> dta = typeAdapters.get(typeAdapter); | |||||
if (dta == null) { | |||||
dta = Utils.newObject(typeAdapter); | |||||
typeAdapters.put(typeAdapter, dta); | |||||
} | } | ||||
dta.setMode(mode); | |||||
return dta; | return dta; | ||||
} | } | ||||
@SuppressWarnings("unchecked") | @SuppressWarnings("unchecked") | ||||
@Override | @Override | ||||
public <T> Object serialize(T value) { | |||||
DataTypeAdapter dta = getAdapter(value.getClass()); | |||||
if (dta == null) { | |||||
public <T> Object serialize(T value, Class<? extends DataTypeAdapter<?>> typeAdapter) { | |||||
if (typeAdapter == null) { | |||||
// pass-through | // pass-through | ||||
return value; | return value; | ||||
} | } | ||||
DataTypeAdapter<T> dta = (DataTypeAdapter<T>) getAdapter(typeAdapter); | |||||
return dta.serialize(value); | return dta.serialize(value); | ||||
} | } | ||||
@Override | @Override | ||||
public Object deserialize(ResultSet rs, int columnIndex, Class<?> targetType) { | |||||
public Object deserialize(ResultSet rs, int columnIndex, Class<?> targetType, Class<? extends DataTypeAdapter<?>> typeAdapter) { | |||||
Object value = null; | Object value = null; | ||||
try { | try { | ||||
DataTypeAdapter<?> dta = getAdapter(targetType); | |||||
if (dta == null) { | |||||
if (typeAdapter == null) { | |||||
// standard object deserialization | // standard object deserialization | ||||
Object o = rs.getObject(columnIndex); | Object o = rs.getObject(columnIndex); | ||||
if (o == null) { | if (o == null) { | ||||
} | } | ||||
} else { | } else { | ||||
// custom object deserialization with a DataTypeAdapter | // custom object deserialization with a DataTypeAdapter | ||||
DataTypeAdapter<?> dta = getAdapter(typeAdapter); | |||||
Object object = rs.getObject(columnIndex); | Object object = rs.getObject(columnIndex); | ||||
value = dta.deserialize(object); | value = dta.deserialize(object); | ||||
} | } | ||||
return o.toString(); | return o.toString(); | ||||
} | } | ||||
} | |||||
} |
buff.appendExceptFirst(", "); | buff.appendExceptFirst(", "); | ||||
buff.append('?'); | buff.append('?'); | ||||
Object value = def.getValue(obj, field); | Object value = def.getValue(obj, field); | ||||
Object parameter = serialize(value); | |||||
Object parameter = serialize(value, field.typeAdapter); | |||||
stat.addParameter(parameter); | stat.addParameter(parameter); | ||||
} | } | ||||
buff.append(')'); | buff.append(')'); |
} | } | ||||
buff.append(')'); | buff.append(')'); | ||||
Object value = def.getValue(obj, field); | Object value = def.getValue(obj, field); | ||||
Object parameter = serialize(value); | |||||
Object parameter = serialize(value, field.typeAdapter); | |||||
stat.addParameter(parameter); | stat.addParameter(parameter); | ||||
} | } | ||||
buff.appendExceptFirst(", "); | buff.appendExceptFirst(", "); | ||||
buff.append('?'); | buff.append('?'); | ||||
Object value = def.getValue(obj, field); | Object value = def.getValue(obj, field); | ||||
Object parameter = serialize(value); | |||||
Object parameter = serialize(value, field.typeAdapter); | |||||
stat.addParameter(parameter); | stat.addParameter(parameter); | ||||
} | } | ||||
buff.append(") ON DUPLICATE KEY UPDATE "); | buff.append(") ON DUPLICATE KEY UPDATE "); |
import java.sql.Time; | import java.sql.Time; | ||||
import java.sql.Timestamp; | import java.sql.Timestamp; | ||||
import com.iciql.Iciql.DataTypeAdapter; | |||||
import com.iciql.TableDefinition.FieldDefinition; | import com.iciql.TableDefinition.FieldDefinition; | ||||
import com.iciql.TableDefinition.IndexDefinition; | import com.iciql.TableDefinition.IndexDefinition; | ||||
import com.iciql.util.IciqlLogger; | import com.iciql.util.IciqlLogger; | ||||
buff.appendExceptFirst(", "); | buff.appendExceptFirst(", "); | ||||
buff.append('?'); | buff.append('?'); | ||||
Object value = def.getValue(obj, field); | Object value = def.getValue(obj, field); | ||||
Object parameter = serialize(value); | |||||
Object parameter = serialize(value, field.typeAdapter); | |||||
stat.addParameter(parameter); | stat.addParameter(parameter); | ||||
} | } | ||||
buff.append(')'); | buff.append(')'); | ||||
} | } | ||||
@Override | @Override | ||||
public Object deserialize(ResultSet rs, int columnIndex, Class<?> targetType) { | |||||
public Object deserialize(ResultSet rs, int columnIndex, Class<?> targetType, Class<? extends DataTypeAdapter<?>> typeAdapter) { | |||||
try { | try { | ||||
return super.deserialize(rs, columnIndex, targetType); | |||||
return super.deserialize(rs, columnIndex, targetType, typeAdapter); | |||||
} catch (IciqlException e) { | } catch (IciqlException e) { | ||||
if (e.getMessage().startsWith("Can not convert")) { | |||||
if (typeAdapter == null && e.getMessage().startsWith("Can not convert")) { | |||||
try { | try { | ||||
// give the SQLite JDBC driver an opportunity to deserialize DateTime objects | // give the SQLite JDBC driver an opportunity to deserialize DateTime objects | ||||
if (Timestamp.class.equals(targetType)) { | if (Timestamp.class.equals(targetType)) { | ||||
} | } | ||||
return super.prepareStringParameter(o); | return super.prepareStringParameter(o); | ||||
} | } | ||||
} | |||||
} |
} | } | ||||
if (typeAdapter != null) { | if (typeAdapter != null) { | ||||
DataTypeAdapter<?> dta = Utils.newObject(typeAdapter); | |||||
dataType = dta.getDataType(); | |||||
db.getDialect().registerAdapter(dta); | |||||
DataTypeAdapter<?> dtt = db.getDialect().getAdapter(typeAdapter); | |||||
dataType = dtt.getDataType(); | |||||
} | } | ||||
boolean hasAnnotation = f.isAnnotationPresent(IQColumn.class); | boolean hasAnnotation = f.isAnnotationPresent(IQColumn.class); | ||||
// try to interpret and instantiate a default value | // try to interpret and instantiate a default value | ||||
value = ModelUtils.getDefaultValue(field, db.getDialect().getDateTimeClass()); | value = ModelUtils.getDefaultValue(field, db.getDialect().getDateTimeClass()); | ||||
} | } | ||||
Object parameter = db.getDialect().serialize(value); | |||||
Object parameter = db.getDialect().serialize(value, field.typeAdapter); | |||||
stat.addParameter(parameter); | stat.addParameter(parameter); | ||||
} | } | ||||
buff.append(')'); | buff.append(')'); | ||||
// try to interpret and instantiate a default value | // try to interpret and instantiate a default value | ||||
value = ModelUtils.getDefaultValue(field, db.getDialect().getDateTimeClass()); | value = ModelUtils.getDefaultValue(field, db.getDialect().getDateTimeClass()); | ||||
} | } | ||||
Object parameter = db.getDialect().serialize(value); | |||||
Object parameter = db.getDialect().serialize(value, field.typeAdapter); | |||||
stat.addParameter(parameter); | stat.addParameter(parameter); | ||||
} | } | ||||
buff.append(')'); | buff.append(')'); | ||||
buff.appendExceptFirst(", "); | buff.appendExceptFirst(", "); | ||||
buff.append(db.getDialect().prepareColumnName(field.columnName)); | buff.append(db.getDialect().prepareColumnName(field.columnName)); | ||||
buff.append(" = ?"); | buff.append(" = ?"); | ||||
Object parameter = db.getDialect().serialize(value); | |||||
Object parameter = db.getDialect().serialize(value, field.typeAdapter); | |||||
stat.addParameter(parameter); | stat.addParameter(parameter); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
o = Utils.convertEnum(obj, targetType, def.enumType); | o = Utils.convertEnum(obj, targetType, def.enumType); | ||||
} else { | } else { | ||||
o = dialect.deserialize(rs, columns[i], targetType); | |||||
o = dialect.deserialize(rs, columns[i], targetType, def.typeAdapter); | |||||
} | } | ||||
def.setValue(item, o); | def.setValue(item, o); | ||||
} | } |