Somewhat major re-factor, all tests pass now

This commit is contained in:
Travis Burtrum 2017-05-17 17:32:48 -04:00
parent b425bb49b0
commit e7639d740c
12 changed files with 132 additions and 78 deletions

View File

@ -132,7 +132,7 @@ public class CachingResultSetMapper extends ResultSetMapper {
}
@Override
protected <T> RowToObjectMapper<T> getRowMapper(ResultSet resultSet, Class<T> returnTypeClass, Calendar cal, Class<?> mapValType) {
return new CachingRowToObjectMapper<T>(cache, resultSet, returnTypeClass, cal, mapValType);
protected <K, T> RowToObjectMapper<K, T> getRowMapper(ResultSet resultSet, Class<T> returnTypeClass, Calendar cal, Class<?> mapValType, Class<K> mapKeyType) {
return new CachingRowToObjectMapper<K, T>(cache, resultSet, returnTypeClass, cal, mapValType, mapKeyType);
}
}

View File

@ -11,18 +11,18 @@ import java.util.Map;
/**
* Maps same as RowToObjectMapper except caches constructor and field mappings
*/
public class CachingRowToObjectMapper<T> extends RowToObjectMapper<T> {
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) {
super(resultSet, returnTypeClass, cal, mapValType);
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);
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);
@ -55,11 +55,12 @@ public class CachingRowToObjectMapper<T> extends RowToObjectMapper<T> {
public static class ResultSetKey {
protected final String[] keys;
protected final Class<?> returnTypeClass;
protected final Class<?> returnTypeClass, mapKeyType;
public ResultSetKey(final String[] keys, final Class<?> returnTypeClass) {
public ResultSetKey(final String[] keys, final Class<?> returnTypeClass, final Class<?> mapKeyType) {
this.keys = keys;
this.returnTypeClass = returnTypeClass;
this.mapKeyType = mapKeyType;
}
@Override
@ -69,13 +70,18 @@ public class CachingRowToObjectMapper<T> extends RowToObjectMapper<T> {
final ResultSetKey that = (ResultSetKey) o;
return Arrays.equals(keys, that.keys) && (returnTypeClass != null ? returnTypeClass.equals(that.returnTypeClass) : that.returnTypeClass == null);
// 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;
}
@ -84,6 +90,7 @@ public class CachingRowToObjectMapper<T> extends RowToObjectMapper<T> {
return "ResultSetKey{" +
"keys=" + Arrays.toString(keys) +
", returnTypeClass=" + returnTypeClass +
", mapKeyType=" + mapKeyType +
'}';
}
}

View File

@ -15,7 +15,7 @@ public class CaseInsensitiveMapResultSetMapper extends ResultSetMapper {
}
@Override
protected <T> RowToObjectMapper<T> getRowMapper(ResultSet resultSet, Class<T> returnTypeClass, Calendar cal, Class<?> mapValType) {
return new CaseInsensitiveMapRowToObjectMapper<T>(resultSet, returnTypeClass, cal, mapValType);
protected <K, T> RowToObjectMapper<K, T> getRowMapper(ResultSet resultSet, Class<T> returnTypeClass, Calendar cal, Class<?> mapValType, Class<K> mapKeyType) {
return new CaseInsensitiveMapRowToObjectMapper<K, T>(resultSet, returnTypeClass, cal, mapValType, mapKeyType);
}
}

View File

@ -8,7 +8,7 @@ import java.util.Map;
/**
* Created by mopar on 5/15/14.
*/
public class CaseInsensitiveMapRowToObjectMapper<T> extends RowToObjectMapper<T> {
public class CaseInsensitiveMapRowToObjectMapper<K, T> extends RowToObjectMapper<K, T> {
public CaseInsensitiveMapRowToObjectMapper(ResultSet resultSet, Class<T> returnTypeClass) {
super(resultSet, returnTypeClass);
}
@ -25,6 +25,10 @@ public class CaseInsensitiveMapRowToObjectMapper<T> extends RowToObjectMapper<T>
super(resultSet, returnTypeClass, cal, mapValType);
}
public CaseInsensitiveMapRowToObjectMapper(ResultSet resultSet, Class<T> returnTypeClass, Calendar cal, Class<?> mapValType, Class<K> mapKeyType) {
super(resultSet, returnTypeClass, cal, mapValType, mapKeyType);
}
@Override
protected Map<String, Object> getMapImplementation() throws IllegalAccessException, InstantiationException {
if(HashMap.class.equals(_returnTypeClass))

View File

@ -19,7 +19,7 @@ public class CleaningResultSetMapper<E> extends ResultSetMapper {
@Override
@SuppressWarnings({"unchecked"})
protected <T> RowToObjectMapper<T> getRowMapper(ResultSet resultSet, Class<T> returnTypeClass, Calendar cal, Class<?> mapValType) {
return new CleaningRowToObjectMapper<T>((Cleaner<T>)cleaner, resultSet, returnTypeClass, cal, mapValType);
protected <K, T> RowToObjectMapper<K, T> getRowMapper(ResultSet resultSet, Class<T> returnTypeClass, Calendar cal, Class<?> mapValType, Class<K> mapKeyType) {
return new CleaningRowToObjectMapper<K, T>((Cleaner<T>)cleaner, resultSet, returnTypeClass, cal, mapValType, mapKeyType);
}
}

View File

@ -1,21 +1,22 @@
package com.moparisthebest.jdbc;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Calendar;
public class CleaningRowToObjectMapper<T> extends RowToObjectMapper<T> {
public class CleaningRowToObjectMapper<K, T> extends RowToObjectMapper<K, T> {
private final Cleaner<T> cleaner;
public CleaningRowToObjectMapper(Cleaner<T> cleaner, ResultSet resultSet, Class<T> returnTypeClass, Calendar cal, Class<?> mapValType) {
super(resultSet, returnTypeClass, cal, mapValType);
public CleaningRowToObjectMapper(Cleaner<T> cleaner, ResultSet resultSet, Class<T> returnTypeClass, Calendar cal, Class<?> mapValType, Class<K> mapKeyType) {
super(resultSet, returnTypeClass, cal, mapValType, mapKeyType);
if (cleaner == null)
throw new NullPointerException("cleaner cannot be null!");
this.cleaner = cleaner;
}
@Override
public T mapRowToReturnType() {
public T mapRowToReturnType() throws SQLException {
return cleaner.clean(super.mapRowToReturnType());
}
}

View File

@ -25,7 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
public class CompilingResultSetMapper extends ResultSetMapper {
protected final Compiler compiler = new Compiler();
protected final Map<CachingRowToObjectMapper.ResultSetKey, CompilingRowToObjectMapper.ResultSetToObject<?>> cache;
protected final Map<CachingRowToObjectMapper.ResultSetKey, CompilingRowToObjectMapper.ResultSetToObject<?,?>> cache;
/**
* CompilingResultSetMapper with optional maxEntries, expiring old ones in LRU fashion
@ -40,14 +40,14 @@ public class CompilingResultSetMapper extends ResultSetMapper {
final float loadFactor = 0.75f; // default for HashMaps
// if we set the initialCapacity this way, nothing should ever need re-sized
final int initialCapacity = ((int) Math.ceil(maxEntries / loadFactor)) + 1;
cache = new LinkedHashMap<CachingRowToObjectMapper.ResultSetKey, CompilingRowToObjectMapper.ResultSetToObject<?>>(initialCapacity, loadFactor, true) {
cache = new LinkedHashMap<CachingRowToObjectMapper.ResultSetKey, CompilingRowToObjectMapper.ResultSetToObject<?,?>>(initialCapacity, loadFactor, true) {
@Override
protected boolean removeEldestEntry(final Map.Entry<CachingRowToObjectMapper.ResultSetKey, CompilingRowToObjectMapper.ResultSetToObject<?>> eldest) {
protected boolean removeEldestEntry(final Map.Entry<CachingRowToObjectMapper.ResultSetKey, CompilingRowToObjectMapper.ResultSetToObject<?,?>> eldest) {
return size() > maxEntries;
}
};
} else
cache = new HashMap<CachingRowToObjectMapper.ResultSetKey, CompilingRowToObjectMapper.ResultSetToObject<?>>();
cache = new HashMap<CachingRowToObjectMapper.ResultSetKey, CompilingRowToObjectMapper.ResultSetToObject<?,?>>();
}
/**
@ -83,7 +83,7 @@ public class CompilingResultSetMapper extends ResultSetMapper {
* @param arrayMaxLength max array/list/map length, a value of less than 1 indicates that all rows from the ResultSet should be included
* @param cache any Map implementation for cache you wish, does not need to handle null keys or values
*/
public CompilingResultSetMapper(final Calendar cal, final int arrayMaxLength, final Map<CachingRowToObjectMapper.ResultSetKey, CompilingRowToObjectMapper.ResultSetToObject<?>> cache) {
public CompilingResultSetMapper(final Calendar cal, final int arrayMaxLength, final Map<CachingRowToObjectMapper.ResultSetKey, CompilingRowToObjectMapper.ResultSetToObject<?,?>> cache) {
super(cal, arrayMaxLength);
if (cache == null)
throw new IllegalArgumentException("cache cannot be null");
@ -96,7 +96,7 @@ public class CompilingResultSetMapper extends ResultSetMapper {
* @param arrayMaxLength max array/list/map length, a value of less than 1 indicates that all rows from the ResultSet should be included
* @param cache any Map implementation for cache you wish, does not need to handle null keys or values
*/
public CompilingResultSetMapper(final int arrayMaxLength, final Map<CachingRowToObjectMapper.ResultSetKey, CompilingRowToObjectMapper.ResultSetToObject<?>> cache) {
public CompilingResultSetMapper(final int arrayMaxLength, final Map<CachingRowToObjectMapper.ResultSetKey, CompilingRowToObjectMapper.ResultSetToObject<?,?>> cache) {
this(null, arrayMaxLength, cache);
}
@ -105,7 +105,7 @@ public class CompilingResultSetMapper extends ResultSetMapper {
*
* @param cache any Map implementation for cache you wish, does not need to handle null keys or values
*/
public CompilingResultSetMapper(final Map<CachingRowToObjectMapper.ResultSetKey, CompilingRowToObjectMapper.ResultSetToObject<?>> cache) {
public CompilingResultSetMapper(final Map<CachingRowToObjectMapper.ResultSetKey, CompilingRowToObjectMapper.ResultSetToObject<?,?>> cache) {
this(-1, cache);
}
@ -118,9 +118,9 @@ public class CompilingResultSetMapper extends ResultSetMapper {
*/
public CompilingResultSetMapper(final Calendar cal, final int arrayMaxLength, final boolean threadSafe) {
this(cal, arrayMaxLength, threadSafe ?
new ConcurrentHashMap<CachingRowToObjectMapper.ResultSetKey, CompilingRowToObjectMapper.ResultSetToObject<?>>()
new ConcurrentHashMap<CachingRowToObjectMapper.ResultSetKey, CompilingRowToObjectMapper.ResultSetToObject<?,?>>()
:
new HashMap<CachingRowToObjectMapper.ResultSetKey, CompilingRowToObjectMapper.ResultSetToObject<?>>()
new HashMap<CachingRowToObjectMapper.ResultSetKey, CompilingRowToObjectMapper.ResultSetToObject<?,?>>()
);
}
@ -144,7 +144,7 @@ public class CompilingResultSetMapper extends ResultSetMapper {
}
@Override
protected <T> RowToObjectMapper<T> getRowMapper(ResultSet resultSet, Class<T> returnTypeClass, Calendar cal, Class<?> mapValType) {
return new CompilingRowToObjectMapper<T>(compiler, cache, resultSet, returnTypeClass, cal, mapValType);
protected <K, T> RowToObjectMapper<K, T> getRowMapper(ResultSet resultSet, Class<T> returnTypeClass, Calendar cal, Class<?> mapValType, Class<K> mapKeyType) {
return new CompilingRowToObjectMapper<K, T>(compiler, cache, resultSet, returnTypeClass, cal, mapValType, mapKeyType);
}
}

View File

@ -26,20 +26,23 @@ import java.util.Map;
* 1. Normally a subclass of RowToObjectMapper can overload the getMapImplementation() method to change some behavior,
* @see CaseInsensitiveMapRowToObjectMapper , but that method is never called with this implementation.
*/
public class CompilingRowToObjectMapper<T> extends RowToObjectMapper<T> {
public class CompilingRowToObjectMapper<K, T> extends RowToObjectMapper<K, T> {
public static final String firstColumnError = "Cannot call getFirstColumn when mapKeyType is null!";
protected final Compiler compiler;
protected final ResultSetToObject<T> resultSetToObject;
protected final ResultSetToObject<K, T> resultSetToObject;
protected String[] keys = null; // for caching if we must generate class
public CompilingRowToObjectMapper(final Compiler compiler, final Map<CachingRowToObjectMapper.ResultSetKey, ResultSetToObject<?>> cache, ResultSet resultSet, Class<T> returnTypeClass, Calendar cal, Class<?> mapValType) {
super(resultSet, returnTypeClass, cal, mapValType);
public CompilingRowToObjectMapper(final Compiler compiler, final Map<CachingRowToObjectMapper.ResultSetKey, ResultSetToObject<?,?>> cache, ResultSet resultSet, Class<T> returnTypeClass, Calendar cal, Class<?> mapValType, Class<K> mapKeyType) {
super(resultSet, returnTypeClass, cal, mapValType, mapKeyType);
this.compiler = compiler;
try {
final CachingRowToObjectMapper.ResultSetKey keys = new CachingRowToObjectMapper.ResultSetKey(super.getKeysFromResultSet(), _returnTypeClass);
final CachingRowToObjectMapper.ResultSetKey keys = new CachingRowToObjectMapper.ResultSetKey(super.getKeysFromResultSet(), _returnTypeClass, _mapKeyType);
//System.out.printf("keys: %s\n", keys);
@SuppressWarnings("unchecked")
final ResultSetToObject<T> resultSetToObject = (ResultSetToObject<T>) cache.get(keys);
final ResultSetToObject<K,T> resultSetToObject = (ResultSetToObject<K,T>) cache.get(keys);
if (resultSetToObject == null) {
//System.out.printf("cache miss, keys: %s\n", keys);
// generate and put into cache
@ -60,15 +63,15 @@ public class CompilingRowToObjectMapper<T> extends RowToObjectMapper<T> {
}
@Override
public T mapRowToReturnType() {
try {
return resultSetToObject.toObject(_resultSet, _cal);
} catch (SQLException e) {
throw new MapperException(e.getMessage(), e);
}
public T mapRowToReturnType() throws SQLException {
return resultSetToObject.toObject(_resultSet, _cal);
}
// todo: generate/cache these to make it faster for Map and MapCollection? maybe just getKey and getVal methods instead
@Override
public K getMapKey() throws SQLException {
return resultSetToObject.getFirstColumn(_resultSet, _cal);
}
// todo: generate/cache these to make it faster for Map and MapCollection? maybe just getKey and getVal methods instead
/*
@Override
public <E> E extractColumnValue(final int index, final Class<E> classType) throws SQLException {
@ -88,11 +91,14 @@ public class CompilingRowToObjectMapper<T> extends RowToObjectMapper<T> {
throw new MapperException("not supported here");
}
public interface ResultSetToObject<T> {
public interface ResultSetToObject<K, T> {
K getFirstColumn(final ResultSet rs, final Calendar cal) throws SQLException;
T toObject(final ResultSet rs, final Calendar cal) throws SQLException;
}
protected String typeFromName(final Class<?> type) {
if(type == null)
return "Object";
if(_columnCount == 1 && type.isPrimitive()) {
// need the object equivalent here, what is the best way? this works, isn't pretty...
if(type.equals(Character.TYPE))
@ -141,27 +147,44 @@ public class CompilingRowToObjectMapper<T> extends RowToObjectMapper<T> {
}
// code generation down here
protected ResultSetToObject<T> genClass() {
protected ResultSetToObject<K, T> genClass() {
final String className = "CompilingMapper";
final String tType = typeFromName(_returnTypeClass);
final String kType = typeFromName(_mapKeyType);
final String header =
"import static com.moparisthebest.jdbc.util.ResultSetUtil.*;\n\n" +
"public final class " + className +
" implements com.moparisthebest.jdbc.CompilingRowToObjectMapper.ResultSetToObject<" + tType + "> {\n" +
" implements com.moparisthebest.jdbc.CompilingRowToObjectMapper.ResultSetToObject<"+ kType +"," + tType + "> {\n" +
" public " + tType + " toObject(final java.sql.ResultSet rs, final java.util.Calendar cal) throws java.sql.SQLException {\n";
final String footer = " }\n" +
final String footer = ";\n }\n" +
"}\n";
final StringBuilder java = new StringBuilder(header);
//java.append("return null;\n");
gen(java, tType);
java.append(" }\n\n public ").append(kType).append(" getFirstColumn(final java.sql.ResultSet rs, final java.util.Calendar cal) throws java.sql.SQLException {\n ");
if(_mapKeyType != null){
java.append("return ");
extractColumnValueString(java, 1, _tmf.getTypeId(_mapKeyType));
} else {
java.append("throw new com.moparisthebest.jdbc.MapperException(com.moparisthebest.jdbc.CompilingRowToObjectMapper.firstColumnError)");
}
java.append(footer);
//System.out.println(java);
System.out.println(java);
return compiler.compile(className, java);
}
protected void gen(final StringBuilder java, final String tType) {
if(mapOnlySecondColumn){
java.append("return ");
extractColumnValueString(java, 2, _tmf.getTypeId(_returnTypeClass));
java.append(";\n");
return;
}
lazyLoadConstructor();
if (resultSetConstructor) {

View File

@ -120,7 +120,7 @@ public class ResultSetMapper {
T ret = null;
try {
if (rs.next())
ret = getRowMapper(rs, componentType, cal, mapValType).mapRowToReturnType();
ret = getRowMapper(rs, componentType, cal, mapValType, null).mapRowToReturnType();
} catch (SQLException e) {
// ignore
}
@ -151,7 +151,7 @@ public class ResultSetMapper {
// a value of less than 1 indicates that all rows from the ResultSet should be included.
final boolean unlimitedRows = arrayMaxLength < 1;
final RowToObjectMapper<E> rowMapper = getRowMapper(rs, componentType, cal, mapValType);
final RowToObjectMapper<?, E> rowMapper = getRowMapper(rs, componentType, cal, mapValType, null);
for (; (unlimitedRows || numRows != arrayMaxLength) && rs.next(); ++numRows) {
E object = rowMapper.mapRowToReturnType();
@ -230,12 +230,11 @@ public class ResultSetMapper {
// a value of less than 1 indicates that all rows from the ResultSet should be included.
final boolean unlimitedRows = arrayMaxLength < 1;
final RowToObjectMapper<E> rowMapper = getRowMapper(rs, componentType, cal, mapValType);
final RowToObjectMapper<K, E> rowMapper = getRowMapper(rs, componentType, cal, mapValType, mapKeyType);
boolean onlyTwoColumns = rowMapper.getColumnCount() == 2;
for (; (unlimitedRows || numRows != arrayMaxLength) && rs.next(); ++numRows) {
K key = rowMapper.extractColumnValue(1, mapKeyType);
E value = onlyTwoColumns ? rowMapper.extractColumnValue(2, componentType) : rowMapper.mapRowToReturnType();
K key = rowMapper.getMapKey();
E value = rowMapper.mapRowToReturnType();
map = softMap.get();
if (map == null)
@ -312,12 +311,11 @@ public class ResultSetMapper {
// a value of less than 1 indicates that all rows from the ResultSet should be included.
final boolean unlimitedRows = arrayMaxLength < 1;
final RowToObjectMapper<C> rowMapper = getRowMapper(rs, componentType, cal, mapValType);
final RowToObjectMapper<K, C> rowMapper = getRowMapper(rs, componentType, cal, mapValType, mapKeyType);
boolean onlyTwoColumns = rowMapper.getColumnCount() == 2;
for (; (unlimitedRows || numRows != arrayMaxLength) && rs.next(); ++numRows) {
K key = rowMapper.extractColumnValue(1, mapKeyType);
C value = onlyTwoColumns ? rowMapper.extractColumnValue(2, componentType) : rowMapper.mapRowToReturnType();
K key = rowMapper.getMapKey();
C value = rowMapper.mapRowToReturnType();
map = softMap.get();
if (map == null)
@ -406,8 +404,8 @@ public class ResultSetMapper {
}
// fairly un-interesting methods below here
protected <T> RowToObjectMapper<T> getRowMapper(ResultSet resultSet, Class<T> returnTypeClass, Calendar cal, Class<?> mapValType) {
return new RowToObjectMapper<T>(resultSet, returnTypeClass, cal, mapValType);
protected <K, T> RowToObjectMapper<K, T> getRowMapper(ResultSet resultSet, Class<T> returnTypeClass, Calendar cal, Class<?> mapValType, Class<K> mapKeyType) {
return new RowToObjectMapper<K, T>(resultSet, returnTypeClass, cal, mapValType, mapKeyType);
}
protected void warnOnMaxLength(final int numRows, final int arrayMaxLength, final ResultSet rs) {

View File

@ -37,7 +37,7 @@ import java.util.regex.Pattern;
* RowMapperFactory.
*
*/
public abstract class RowMapper {
public abstract class RowMapper<K, T> {
private static final String SETTER_NAME_REGEX = "^(set)([A-Z_]\\w*+)";
protected static final TypeMappingsFactory _tmf = TypeMappingsFactory.getInstance();
@ -50,34 +50,51 @@ public abstract class RowMapper {
protected final Calendar _cal;
/** Class to map ResultSet Rows to. */
protected final Class<?> _returnTypeClass;
protected final Class<T> _returnTypeClass;
protected final Class<K> _mapKeyType;
protected final int _columnCount;
protected final boolean mapOnlySecondColumn;
/**
* Create a new RowMapper for the specified ResultSet and return type Class.
* @param resultSet ResultSet to map
* @param returnTypeClass Class to map ResultSet rows to.
* @param cal Calendar instance for date/time values.
*/
protected RowMapper(ResultSet resultSet, Class<?> returnTypeClass, Calendar cal) {
protected RowMapper(ResultSet resultSet, Class<T> returnTypeClass, Calendar cal, Class<K> mapKeyType) {
_resultSet = resultSet;
_returnTypeClass = returnTypeClass;
_cal = cal;
_mapKeyType = mapKeyType;
try {
_columnCount = resultSet.getMetaData().getColumnCount();
} catch (SQLException e) {
throw new MapperException("RowToObjectMapper: SQLException: " + e.getMessage(), e);
}
mapOnlySecondColumn = _mapKeyType != null && _columnCount == 2;
}
protected RowMapper(ResultSet resultSet, Class<T> returnTypeClass, Calendar cal) {
this(resultSet, returnTypeClass, cal, null);
}
/**
* Map a ResultSet row to the return type class
* @return An instance of class.
* @return An instance of class, if _mapKeyType is not null and _columnCount is 2, return only index 2
*/
public abstract Object mapRowToReturnType();
public abstract T mapRowToReturnType() throws SQLException;
/**
* key for map
* @return index number 1, with type of _mapKeyType
* @throws MapperException if _mapKeyType is null
*/
public abstract K getMapKey() throws SQLException;
/**
* Build a String array of column names from the ResultSet.

View File

@ -47,7 +47,7 @@ import static com.moparisthebest.jdbc.UpdateableDTO.NO;
*
* @author Travis Burtrum (modifications from beehive)
*/
public class RowToObjectMapper<T> extends RowMapper {
public class RowToObjectMapper<K, T> extends RowMapper<K, T> {
public static final int TYPE_BOOLEAN = _tmf.getTypeId(Boolean.TYPE);//TypeMappingsFactory.TYPE_BOOLEAN; // not public?
public static final int TYPE_BOOLEAN_OBJ = _tmf.getTypeId(Boolean.class);//TypeMappingsFactory.TYPE_BOOLEAN_OBJ; // not public?
@ -77,6 +77,11 @@ public class RowToObjectMapper<T> extends RowMapper {
this(resultSet, returnTypeClass, cal, null);
}
public RowToObjectMapper(ResultSet resultSet, Class<T> returnTypeClass, Calendar cal, Class<?> mapValType) {
this(resultSet, returnTypeClass, cal, mapValType, null);
}
/**
* Create a new RowToObjectMapper.
*
@ -84,8 +89,8 @@ public class RowToObjectMapper<T> extends RowMapper {
* @param returnTypeClass Class to map to.
* @param cal Calendar instance for date/time mappings.
*/
public RowToObjectMapper(ResultSet resultSet, Class<T> returnTypeClass, Calendar cal, Class<?> mapValType) {
super(resultSet, returnTypeClass, cal);
public RowToObjectMapper(ResultSet resultSet, Class<T> returnTypeClass, Calendar cal, Class<?> mapValType, Class<K> mapKeyType) {
super(resultSet, returnTypeClass, cal, mapKeyType);
returnMap = Map.class.isAssignableFrom(returnTypeClass);
if(returnMap){
_returnTypeClass = ResultSetMapper.getConcreteClass(returnTypeClass, HashMap.class);
@ -136,13 +141,21 @@ public class RowToObjectMapper<T> extends RowMapper {
return (Map<String, Object>)_returnTypeClass.newInstance();
}
@Override
public K getMapKey() throws SQLException {
return this.extractColumnValue(1, _mapKeyType);
}
/**
* Do the mapping.
*
* @return An object instance.
*/
@SuppressWarnings({"unchecked"})
public T mapRowToReturnType() {
public T mapRowToReturnType() throws SQLException {
if(mapOnlySecondColumn)
return this.extractColumnValue(2, _returnTypeClass);
lazyLoadConstructor();
@ -300,15 +313,6 @@ public class RowToObjectMapper<T> extends RowMapper {
return classType.cast(extractColumnValue(index, _tmf.getTypeId(classType)));
}
/**
* Provided so we know whether to map all values to a type, or just the second one
*
* @return
*/
public int getColumnCount() {
return this._columnCount;
}
/**
* Build the structures necessary to do the mapping
*

View File

@ -9,7 +9,7 @@ import java.util.concurrent.ConcurrentHashMap;
*/
public class StaticCompilingResultSetMapper extends CompilingResultSetMapper {
private static final Map<CachingRowToObjectMapper.ResultSetKey, CompilingRowToObjectMapper.ResultSetToObject<?>> cache = new ConcurrentHashMap<CachingRowToObjectMapper.ResultSetKey, CompilingRowToObjectMapper.ResultSetToObject<?>>();
private static final Map<CachingRowToObjectMapper.ResultSetKey, CompilingRowToObjectMapper.ResultSetToObject<?,?>> cache = new ConcurrentHashMap<CachingRowToObjectMapper.ResultSetKey, CompilingRowToObjectMapper.ResultSetToObject<?,?>>();
public static final StaticCompilingResultSetMapper instance = new StaticCompilingResultSetMapper();