112 lines
3.7 KiB
Java
112 lines
3.7 KiB
Java
package com.moparisthebest.jdbc;
|
|
|
|
import java.lang.reflect.AccessibleObject;
|
|
import java.lang.reflect.Constructor;
|
|
import java.sql.ResultSet;
|
|
import java.sql.SQLException;
|
|
import java.util.Arrays;
|
|
import java.util.Calendar;
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* Maps same as RowToObjectMapper except caches constructor and field mappings
|
|
*/
|
|
public class CachingRowToObjectMapper<K, T> extends RowToObjectMapper<K, T> {
|
|
|
|
protected final Map<ResultSetKey, FieldMapping<T>> cache;
|
|
protected final ResultSetKey keys;
|
|
|
|
public CachingRowToObjectMapper(final Map<ResultSetKey, FieldMapping<?>> cache, ResultSet resultSet, Class<T> returnTypeClass, Calendar cal, Class<?> mapValType, Class<K> mapKeyType) {
|
|
super(resultSet, returnTypeClass, cal, mapValType, mapKeyType);
|
|
@SuppressWarnings("unchecked")
|
|
final Map<ResultSetKey, FieldMapping<T>> genericCache = (Map<ResultSetKey, FieldMapping<T>>) (Object) cache; // ridiculous ain't it?
|
|
this.cache = genericCache;
|
|
try {
|
|
keys = new ResultSetKey(super.getKeysFromResultSet(), _returnTypeClass, _mapKeyType);
|
|
//System.out.printf("keys: %s\n", keys);
|
|
} catch (SQLException e) {
|
|
throw new MapperException("CachingRowToObjectMapper: SQLException: " + e.getMessage(), e);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected String[] getKeysFromResultSet() throws SQLException {
|
|
return keys.keys;
|
|
}
|
|
|
|
@Override
|
|
protected void getFieldMappings() throws SQLException {
|
|
final FieldMapping<T> fm = cache.get(keys);
|
|
if (fm == null) {
|
|
//System.out.printf("cache miss, keys: %s\n", keys);
|
|
// generate and put into cache
|
|
super.getFieldMappings();
|
|
cache.put(keys, new FieldMapping<T>(_fields, _fieldTypes, resultSetConstructor, constructor));
|
|
} else {
|
|
//System.out.printf("cache hit, keys: %s\n", keys);
|
|
// load from cache
|
|
_fields = fm._fields;
|
|
_fieldTypes = fm._fieldTypes;
|
|
resultSetConstructor = fm.resultSetConstructor;
|
|
constructor = fm.constructor;
|
|
constructorLoaded = true;
|
|
}
|
|
}
|
|
|
|
public static class ResultSetKey {
|
|
protected final String[] keys;
|
|
protected final Class<?> returnTypeClass, mapKeyType;
|
|
|
|
public ResultSetKey(final String[] keys, final Class<?> returnTypeClass, final Class<?> mapKeyType) {
|
|
this.keys = keys;
|
|
this.returnTypeClass = returnTypeClass;
|
|
this.mapKeyType = mapKeyType;
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(final Object o) {
|
|
if (this == o) return true;
|
|
if (!(o instanceof ResultSetKey)) return false;
|
|
|
|
final ResultSetKey that = (ResultSetKey) o;
|
|
|
|
// Probably incorrect - comparing Object[] arrays with Arrays.equals
|
|
if (!Arrays.equals(keys, that.keys)) return false;
|
|
if (returnTypeClass != null ? !returnTypeClass.equals(that.returnTypeClass) : that.returnTypeClass != null)
|
|
return false;
|
|
return mapKeyType != null ? mapKeyType.equals(that.mapKeyType) : that.mapKeyType == null;
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
int result = Arrays.hashCode(keys);
|
|
result = 31 * result + (returnTypeClass != null ? returnTypeClass.hashCode() : 0);
|
|
result = 31 * result + (mapKeyType != null ? mapKeyType.hashCode() : 0);
|
|
return result;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return "ResultSetKey{" +
|
|
"keys=" + Arrays.toString(keys) +
|
|
", returnTypeClass=" + returnTypeClass +
|
|
", mapKeyType=" + mapKeyType +
|
|
'}';
|
|
}
|
|
}
|
|
|
|
static class FieldMapping<T> {
|
|
public final AccessibleObject[] _fields;
|
|
public final int[] _fieldTypes;
|
|
public final boolean resultSetConstructor;
|
|
public final Constructor<? extends T> constructor;
|
|
|
|
public FieldMapping(final AccessibleObject[] _fields, final int[] _fieldTypes, final boolean resultSetConstructor, final Constructor<? extends T> constructor) {
|
|
this._fields = _fields;
|
|
this._fieldTypes = _fieldTypes;
|
|
this.resultSetConstructor = resultSetConstructor;
|
|
this.constructor = constructor;
|
|
}
|
|
}
|
|
}
|