First commit of beehive-jdbc-mapper, which has no dependencies, but which beehive-jdbc-control now depends on

This commit is contained in:
moparisthebest 2014-04-22 14:40:18 -04:00
parent 39338e999f
commit d0e1e03756
23 changed files with 5699 additions and 0 deletions

View File

@ -33,6 +33,11 @@
<artifactId>beehive-controls</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.moparisthebest.beehive</groupId>
<artifactId>beehive-jdbc-mapper</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.moparisthebest.aptIn16</groupId>
<artifactId>netui-compiler</artifactId>

View File

@ -0,0 +1,56 @@
package org.apache.beehive.controls.system.jdbc;
import org.apache.beehive.controls.api.context.ControlBeanContext;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.ResultSet;
import java.util.*;
/**
* Refer to org.apache.beehive.controls.system.jdbc.ResultSetMapper for how this class operates
*/
public class NewDefaultObjectResultSetMapper extends com.moparisthebest.jdbc.ResultSetMapper implements org.apache.beehive.controls.system.jdbc.ResultSetMapper {
/**
* Map the ResultSet to the method's return type. The object type returned is defined by the return type of the method.
*
* @param context A ControlBeanContext instance, see Beehive controls javadoc for additional information
* @param m Method assoicated with this call.
* @param rs Result set to map.
* @param cal A Calendar instance for time/date value resolution.
* @return The Object resulting from the ResultSet
*/
@SuppressWarnings({"unchecked"})
public Object mapToResultType(ControlBeanContext context, Method m, ResultSet rs, Calendar cal) {
final Class returnType = m.getReturnType();
if (returnType.isArray()) {
return toArray(rs, returnType.getComponentType(), context.getMethodPropertySet(m, JdbcControl.SQL.class).arrayMaxLength(), cal);
} else if (Collection.class.isAssignableFrom(returnType)) {
return toCollection(rs, returnType, (Class) getActualTypeArguments(m)[0], context.getMethodPropertySet(m, JdbcControl.SQL.class).arrayMaxLength(), cal);
} else if (Map.class.isAssignableFrom(returnType)) {
Type[] types = getActualTypeArguments(m);
if (types[1] instanceof ParameterizedType) { // for collectionMaps
ParameterizedType pt = (ParameterizedType) types[1];
Class collectionType = (Class) pt.getRawType();
if (Collection.class.isAssignableFrom(collectionType))
return toMapCollection(rs, returnType, (Class) types[0], collectionType, (Class) pt.getActualTypeArguments()[0], context.getMethodPropertySet(m, JdbcControl.SQL.class).arrayMaxLength(), cal);
}
return toMap(rs, returnType, (Class) types[0], (Class) types[1], context.getMethodPropertySet(m, JdbcControl.SQL.class).arrayMaxLength(), cal);
} else if (Iterator.class.isAssignableFrom(returnType)) {
return ListIterator.class.isAssignableFrom(returnType) ?
toListIterator(rs, (Class) getActualTypeArguments(m)[0], context.getMethodPropertySet(m, JdbcControl.SQL.class).arrayMaxLength(), cal) :
toIterator(rs, (Class) getActualTypeArguments(m)[0], context.getMethodPropertySet(m, JdbcControl.SQL.class).arrayMaxLength(), cal);
} else {
return toObject(rs, returnType, cal);
}
}
private static Type[] getActualTypeArguments(Method m) {
return ((ParameterizedType) m.getGenericReturnType()).getActualTypeArguments();
}
public boolean canCloseResultSet() {
return true;
}
}

View File

@ -0,0 +1,117 @@
#!/bin/bash
cd "$(dirname "$0")"
function prepareFile(){
path="$1"
tmp_path="$(basename "$path")"
(
sed -n '/CODE AUTOMATICALLY GENERATED BY genQueryMapper.sh/q;p' "$path"
echo -e '\t// DO NOT EDIT BELOW THIS LINE, OR CHANGE THIS COMMENT, CODE AUTOMATICALLY GENERATED BY genQueryMapper.sh\n'
) > "$tmp_path"
echo "$tmp_path"
}
function finishFile(){
path="$1"
tmp_path="$(basename "$path")"
echo -e "}\n" >> "$tmp_path"
mv "$tmp_path" "$path"
}
result="$(prepareFile "src/main/java/com/moparisthebest/jdbc/ResultSetMapper.java")"
# single object types
cat src/main/java/com/moparisthebest/jdbc/ResultSetMapper.java | grep public | egrep '(toObject|toSingleMap)\(' | grep ', Calendar cal)' | while read method
do
#echo "method: $method"
method_name=$(echo $method | egrep -o '[^ ]+\(')
echo "ResultSetMapper.$method_name)"
cat >> "$result" <<EOF
$(echo $method | sed "s/, Calendar cal)/)/")
return this.$method_name$(echo $method | sed -e 's/^.*(//' -e 's/final //g' -e 's/, [^ ]* /, /g' -e 's/ResultSet rs/rs/' -e 's/) {/);/')
}
EOF
done
#everything else
cat src/main/java/com/moparisthebest/jdbc/ResultSetMapper.java | grep public | grep '(ResultSet rs' | grep ', int arrayMaxLength, Calendar cal)' | while read method
do
#echo "method: $method"
method_name=$(echo $method | egrep -o '[^ ]+\(')
echo "ResultSetMapper.$method_name)"
for args in '' ', int arrayMaxLength' ', Calendar cal'
do
cat >> "$result" <<EOF
$(echo $method | sed "s/, int arrayMaxLength, Calendar cal)/$args)/")
return this.$method_name$(echo $method | sed -e 's/^.*(//' -e 's/final //g' -e 's/, [^ ]* /, /g' -e 's/ResultSet rs/rs/' -e 's/) {/);/')
}
EOF
done
done
finishFile "src/main/java/com/moparisthebest/jdbc/ResultSetMapper.java"
query="$(prepareFile "src/main/java/com/moparisthebest/jdbc/QueryMapper.java")"
caching_query="$(prepareFile "src/main/java/com/moparisthebest/jdbc/CachingQueryMapper.java")"
null_query="$(prepareFile "src/main/java/com/moparisthebest/jdbc/NullQueryMapper.java")"
cat src/main/java/com/moparisthebest/jdbc/ResultSetMapper.java | grep public | grep '(ResultSet rs' | egrep -v '(int arrayMaxLength|Calendar cal)' | while read method
do
#echo "method: $method"
method_name=$(echo $method | egrep -o '[^ ]+\(')
echo "QueryMapper.$method_name)"
# QueryMapper.java
cat >> "$query" <<EOF
$(echo $method | sed -e 's/ResultSet rs/PreparedStatement ps/' -e 's/) {/, final Object... bindObjects) throws SQLException {/')
return cm.$method_name$(echo $method | sed -e 's/^.*(//' -e 's/final //g' -e 's/, [^ ]* /, /g' -e 's/ResultSet rs/bindExecute(ps, bindObjects)/' -e 's/) {/);/')
}
$(echo $method | sed -e 's/ResultSet rs/String sql/' -e 's/) {/, final Object... bindObjects) throws SQLException {/')
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.$method_name$(echo $method | sed -e 's/^.*(//' -e 's/final //g' -e 's/, [^ ]* /, /g' -e 's/ResultSet rs/ps/' -e 's/) {/, bindObjects);/')
} finally {
tryClose(ps);
}
}
EOF
# CachingQueryMapper.java
cat >> "$caching_query" <<EOF
@Override
$(echo $method | sed -e 's/ResultSet rs/String sql/' -e 's/) {/, final Object... bindObjects) throws SQLException {/')
return super.$method_name$(echo $method | sed -e 's/^.*(//' -e 's/final //g' -e 's/, [^ ]* /, /g' -e 's/ResultSet rs/getPreparedStatement(sql)/' -e 's/) {/, bindObjects);/')
}
EOF
# NullQueryMapper.java
for type in PreparedStatement String
do
cat <<EOF
@Override
$(echo $method | sed -e "s/ResultSet rs/$type query/" -e 's/) {/, final Object... bindObjects) {/')
try {
return delegate.$method_name$(echo $method | sed -e 's/^.*(//' -e 's/final //g' -e 's/, [^ ]* /, /g' -e 's/ResultSet rs/query/' -e 's/) {/, bindObjects);/')
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
EOF
done >> "$null_query"
done
finishFile "src/main/java/com/moparisthebest/jdbc/QueryMapper.java"
finishFile "src/main/java/com/moparisthebest/jdbc/CachingQueryMapper.java"
finishFile "src/main/java/com/moparisthebest/jdbc/NullQueryMapper.java"

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.moparisthebest.beehive</groupId>
<artifactId>beehive</artifactId>
<version>1.0.3-SNAPSHOT</version>
</parent>
<artifactId>beehive-jdbc-mapper</artifactId>
<name>${project.artifactId}</name>
<build>
<finalName>${project.artifactId}</finalName>
</build>
</project>

View File

@ -0,0 +1,296 @@
package com.moparisthebest.jdbc;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import static com.moparisthebest.jdbc.TryClose.tryClose;
/**
* This class caches the PreparedStatement's it creates for the strings you send in, then closes them when the close() method is called.
* Since PreparedStatement is not thread-safe, this class cannot be either. Be sure to call it from only a single thread
* or synchronize around it.
*/
public class CachingQueryMapper extends QueryMapper {
protected final Map<String, PreparedStatement> cache;
protected CachingQueryMapper(Connection conn, String jndiName, ResultSetMapper cm, final int maxEntries) {
super(conn, jndiName, cm);
if (maxEntries > 0) { // we want a limited cache
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<String, PreparedStatement>(initialCapacity, loadFactor, true) {
@Override
protected boolean removeEldestEntry(Map.Entry<String, PreparedStatement> eldest) {
final boolean remove = size() > maxEntries;
if(remove){
//System.out.printf("closing PreparedStatement '%s' with key '%s'\n", eldest.getValue(), eldest.getKey());
tryClose(eldest.getValue());
}
return remove;
}
};
} else
cache = new HashMap<String, PreparedStatement>();
}
public CachingQueryMapper(Connection conn, ResultSetMapper cm, final int maxEntries) {
this(conn, null, cm, maxEntries);
}
public CachingQueryMapper(Connection conn, final int maxEntries) {
this(conn, null, null, maxEntries);
}
public CachingQueryMapper(String jndiName, ResultSetMapper cm, final int maxEntries) {
this(null, jndiName, cm, maxEntries);
}
public CachingQueryMapper(String jndiName, final int maxEntries) {
this(null, jndiName, null, maxEntries);
}
protected CachingQueryMapper(Connection conn, String jndiName, ResultSetMapper cm) {
this(conn, jndiName, cm, 20); // default size of 20
}
public CachingQueryMapper(Connection conn, ResultSetMapper cm) {
this(conn, null, cm);
}
public CachingQueryMapper(Connection conn) {
this(conn, null, null);
}
public CachingQueryMapper(String jndiName, ResultSetMapper cm) {
this(null, jndiName, cm);
}
public CachingQueryMapper(String jndiName) {
this(null, jndiName, null);
}
protected PreparedStatement getPreparedStatement(String sql) throws SQLException {
return getPreparedStatement(sql, ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_READ_ONLY);
}
protected PreparedStatement getPreparedStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
PreparedStatement ps = cache.get(sql);
if (ps == null) {
//System.out.println("cache miss");
ps = conn.prepareStatement(sql,resultSetType,resultSetConcurrency);
cache.put(sql, ps);
}
//else System.out.println("cache hit");
return ps;
}
public void clearCache(boolean close) {
//System.out.println("cache size: "+cache.size());
for (PreparedStatement ps : cache.values())
tryClose(ps);
if (close)
super.close();
else
cache.clear();
}
public void clearCache() {
this.clearCache(false);
}
@Override
public void close() {
this.clearCache(true);
}
@Override
public int executeUpdate(String sql, Object... bindObjects) throws SQLException {
return super.executeUpdate(getPreparedStatement(sql), bindObjects);
}
@Override
public boolean executeUpdateSuccess(String sql, Object... bindObjects) throws SQLException {
return super.executeUpdateSuccess(getPreparedStatement(sql), bindObjects);
}
// these grab ResultSets from the database
@Override
public ResultSet toResultSet(String sql, Object... bindObjects) throws SQLException {
return super.toResultSet(getPreparedStatement(sql), bindObjects);
}
@Override
public ResultSet toResultSet(String sql, Integer rsType, Integer rsConcurrency, Object... bindObjects) throws SQLException {
return super.toResultSet(getPreparedStatement(sql,rsType,rsConcurrency), bindObjects);
}
// DO NOT EDIT BELOW THIS LINE, OR CHANGE THIS COMMENT, CODE AUTOMATICALLY GENERATED BY genQueryMapper.sh
@Override
public <T> T toObject(String sql, Class<T> componentType, final Object... bindObjects) throws SQLException {
return super.toObject(getPreparedStatement(sql), componentType, bindObjects);
}
@Override
public <T extends Map<String, V>, V> Map<String, V> toSingleMap(String sql, Class<T> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return super.toSingleMap(getPreparedStatement(sql), componentType, mapValType, bindObjects);
}
@Override
public <V> Map<String, V> toSingleMap(String sql, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return super.toSingleMap(getPreparedStatement(sql), mapValType, bindObjects);
}
@Override
public <T extends Collection<E>, E> T toCollection(String sql, final Class<T> collectionType, Class<E> componentType, final Object... bindObjects) throws SQLException {
return super.toCollection(getPreparedStatement(sql), collectionType, componentType, bindObjects);
}
@Override
public <T extends Collection<E>, E> T toCollection(String sql, T list, Class<E> componentType, final Object... bindObjects) throws SQLException {
return super.toCollection(getPreparedStatement(sql), list, componentType, bindObjects);
}
@Override
public <T extends Map<K, E>, K, E> T toMap(String sql, final Class<T> returnType, Class<K> mapKeyType, Class<E> componentType, final Object... bindObjects) throws SQLException {
return super.toMap(getPreparedStatement(sql), returnType, mapKeyType, componentType, bindObjects);
}
@Override
public <T extends Map<K, E>, K, E> T toMap(String sql, T map, Class<K> mapKeyType, Class<E> componentType, final Object... bindObjects) throws SQLException {
return super.toMap(getPreparedStatement(sql), map, mapKeyType, componentType, bindObjects);
}
@Override
public <T extends Map<K, E>, K, E extends Collection<C>, C> T toMapCollection(String sql, final Class<T> returnType, Class<K> mapKeyType, Class<E> collectionType, Class<C> componentType, final Object... bindObjects) throws SQLException {
return super.toMapCollection(getPreparedStatement(sql), returnType, mapKeyType, collectionType, componentType, bindObjects);
}
@Override
public <T extends Map<K, E>, K, E extends Collection<C>, C> T toMapCollection(String sql, T map, Class<K> mapKeyType, Class<E> collectionType, Class<C> componentType, final Object... bindObjects) throws SQLException {
return super.toMapCollection(getPreparedStatement(sql), map, mapKeyType, collectionType, componentType, bindObjects);
}
@Override
public <T> ListIterator<T> toListIterator(String sql, final Class<T> type, final Object... bindObjects) throws SQLException {
return super.toListIterator(getPreparedStatement(sql), type, bindObjects);
}
@Override
public <T> Iterator<T> toIterator(String sql, final Class<T> type, final Object... bindObjects) throws SQLException {
return super.toIterator(getPreparedStatement(sql), type, bindObjects);
}
@Override
public <T> T[] toArray(String sql, final Class<T> type, final Object... bindObjects) throws SQLException {
return super.toArray(getPreparedStatement(sql), type, bindObjects);
}
@Override
public <E> List<E> toList(String sql, Class<E> componentType, final Object... bindObjects) throws SQLException {
return super.toList(getPreparedStatement(sql), componentType, bindObjects);
}
@Override
public <K, E> Map<K, E> toMap(String sql, Class<K> mapKeyType, Class<E> componentType, final Object... bindObjects) throws SQLException {
return super.toMap(getPreparedStatement(sql), mapKeyType, componentType, bindObjects);
}
@Override
public <K, E extends List<C>, C> Map<K, E> toMapList(String sql, Class<K> mapKeyType, Class<C> componentType, final Object... bindObjects) throws SQLException {
return super.toMapList(getPreparedStatement(sql), mapKeyType, componentType, bindObjects);
}
@Override
public <T extends Collection<E>, E extends Map<String, V>, V> T toCollectionMap(String sql, final Class<T> collectionType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return super.toCollectionMap(getPreparedStatement(sql), collectionType, componentType, mapValType, bindObjects);
}
@Override
public <T extends Collection<E>, E extends Map<String, V>, V> T toCollectionMap(String sql, T list, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return super.toCollectionMap(getPreparedStatement(sql), list, componentType, mapValType, bindObjects);
}
@Override
public <T extends Map<K, E>, K, E extends Map<String, V>, V> T toMapMap(String sql, final Class<T> returnType, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return super.toMapMap(getPreparedStatement(sql), returnType, mapKeyType, componentType, mapValType, bindObjects);
}
@Override
public <T extends Map<K, E>, K, E extends Map<String, V>, V> T toMapMap(String sql, T map, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return super.toMapMap(getPreparedStatement(sql), map, mapKeyType, componentType, mapValType, bindObjects);
}
@Override
public <T extends Map<K, C>, K, C extends Collection<E>, E extends Map<String, V>, V> T toMapCollectionMap(String sql, final Class<T> returnType, Class<K> mapKeyType, Class<C> collectionType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return super.toMapCollectionMap(getPreparedStatement(sql), returnType, mapKeyType, collectionType, componentType, mapValType, bindObjects);
}
@Override
public <T extends Map<K, C>, K, C extends Collection<E>, E extends Map<String, V>, V> T toMapCollectionMap(String sql, T map, Class<K> mapKeyType, Class<C> collectionType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return super.toMapCollectionMap(getPreparedStatement(sql), map, mapKeyType, collectionType, componentType, mapValType, bindObjects);
}
@Override
public <T extends Map<String, V>, V> ListIterator<Map<String, V>> toListIteratorMap(String sql, final Class<T> type, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return super.toListIteratorMap(getPreparedStatement(sql), type, mapValType, bindObjects);
}
@Override
public <T extends Map<String, V>, V> Iterator<Map<String, V>> toIteratorMap(String sql, final Class<T> type, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return super.toIteratorMap(getPreparedStatement(sql), type, mapValType, bindObjects);
}
@Override
public <T extends Map<String, V>, V> Map<String, V>[] toArrayMap(String sql, final Class<T> type, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return super.toArrayMap(getPreparedStatement(sql), type, mapValType, bindObjects);
}
@Override
public <E extends Map<String, V>, V> List<Map<String, V>> toListMap(String sql, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return super.toListMap(getPreparedStatement(sql), componentType, mapValType, bindObjects);
}
@Override
public <K, E extends Map<String, V>, V> Map<K, Map<String, V>> toMapMap(String sql, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return super.toMapMap(getPreparedStatement(sql), mapKeyType, componentType, mapValType, bindObjects);
}
@Override
public <K, E extends Map<String, V>, V> Map<K, List<Map<String, V>>> toMapListMap(String sql, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return super.toMapListMap(getPreparedStatement(sql), mapKeyType, componentType, mapValType, bindObjects);
}
@Override
public <V> ListIterator<Map<String, V>> toListIteratorMap(String sql, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return super.toListIteratorMap(getPreparedStatement(sql), mapValType, bindObjects);
}
@Override
public <V> Iterator<Map<String, V>> toIteratorMap(String sql, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return super.toIteratorMap(getPreparedStatement(sql), mapValType, bindObjects);
}
@Override
public <V> List<Map<String, V>> toListMap(String sql, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return super.toListMap(getPreparedStatement(sql), mapValType, bindObjects);
}
@Override
public <K, V> Map<K, Map<String, V>> toMapMap(String sql, Class<K> mapKeyType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return super.toMapMap(getPreparedStatement(sql), mapKeyType, mapValType, bindObjects);
}
@Override
public <K, V> Map<K, List<Map<String, V>>> toMapListMap(String sql, Class<K> mapKeyType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return super.toMapListMap(getPreparedStatement(sql), mapKeyType, mapValType, bindObjects);
}
}

View File

@ -0,0 +1,20 @@
package com.moparisthebest.jdbc;
import java.sql.ResultSet;
import java.util.Calendar;
public class CachingResultSetMapper extends ResultSetMapper {
public CachingResultSetMapper(Calendar cal, int arrayMaxLength) {
super(cal, arrayMaxLength);
}
public CachingResultSetMapper() {
super();
}
@Override
protected <T> RowToObjectMapper<T> getRowMapper(ResultSet resultSet, Class<T> returnTypeClass, Calendar cal, Class<?> mapValType) {
return new CachingRowToObjectMapper<T>(resultSet, returnTypeClass, cal, mapValType);
}
}

View File

@ -0,0 +1,65 @@
package com.moparisthebest.jdbc;
import java.lang.reflect.AccessibleObject;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
public class CachingRowToObjectMapper<T> extends RowToObjectMapper<T> {
protected static final Map<Integer, FieldMapping> cache = new HashMap<Integer, FieldMapping>();
protected final int thisHash;
protected final String[] keys;
public CachingRowToObjectMapper(ResultSet resultSet, Class<T> returnTypeClass, Calendar cal, Class<?> mapValType) {
super(resultSet, returnTypeClass, cal, mapValType);
try {
keys = super.getKeysFromResultSet();
//System.out.printf("keys: %d, %s: %d\n", Arrays.hashCode(keys), _returnTypeClass, _returnTypeClass.hashCode());
thisHash = Arrays.hashCode(keys) ^ _returnTypeClass.hashCode();
} catch (SQLException e) {
throw new MapperException("CachingRowToObjectMapper: SQLException: " + e.getMessage(), e);
}
}
@Override
protected String[] getKeysFromResultSet() throws SQLException {
return keys;
}
@Override
protected void getFieldMappings() throws SQLException {
FieldMapping fm = cache.get(thisHash);
if (fm == null) {
//System.out.printf("cache miss, hashcode: %d\n", thisHash);
// generate and put into cache
super.getFieldMappings();
synchronized (cache) {
// I *think* we only need to synchronize here, instead of around the get as well
// it may allow some leaks (field mappings being generated more than once)
// but the performance benefits of not having this entire method synchronized
// statically probably outweighs the negatives
cache.put(thisHash, new FieldMapping(_fields, _fieldTypes));
}
} else {
//System.out.printf("cache hit, hashcode: %d\n", thisHash);
// load from cache
_fields = fm._fields;
_fieldTypes = fm._fieldTypes;
}
}
private static class FieldMapping {
public final AccessibleObject[] _fields;
public final int[] _fieldTypes;
private FieldMapping(AccessibleObject[] _fields, int[] _fieldTypes) {
this._fields = _fields;
this._fieldTypes = _fieldTypes;
}
}
}

View File

@ -0,0 +1,6 @@
package com.moparisthebest.jdbc;
public interface Cleaner<T> {
public T clean(T dto);
}

View File

@ -0,0 +1,25 @@
package com.moparisthebest.jdbc;
import java.sql.ResultSet;
import java.util.Calendar;
public class CleaningResultSetMapper<E> extends ResultSetMapper {
private final Cleaner<E> cleaner;
public CleaningResultSetMapper(Cleaner<E> cleaner, Calendar cal, int arrayMaxLength) {
super(cal, arrayMaxLength);
this.cleaner = cleaner;
}
public CleaningResultSetMapper(Cleaner<E> cleaner) {
super();
this.cleaner = cleaner;
}
@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);
}
}

View File

@ -0,0 +1,21 @@
package com.moparisthebest.jdbc;
import java.sql.ResultSet;
import java.util.Calendar;
public class CleaningRowToObjectMapper<T> extends RowToObjectMapper<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);
if (cleaner == null)
throw new NullPointerException("cleaner cannot be null!");
this.cleaner = cleaner;
}
@Override
public T mapRowToReturnType() {
return cleaner.clean(super.mapRowToReturnType());
}
}

View File

@ -0,0 +1,8 @@
package com.moparisthebest.jdbc;
import java.sql.ResultSet;
import java.sql.SQLException;
public interface Finishable {
public void finish(ResultSet rs) throws SQLException;
}

View File

@ -0,0 +1,45 @@
package com.moparisthebest.jdbc;
/**
* The MapperException class declares an unchecked exception that is thrown by the Controls
* runtime under certain failure conditions.
*/
public class MapperException extends RuntimeException
{
/**
* Default constructor.
*/
public MapperException() {
super();
}
/**
* Constructs a MapperException object with the specified String as a message.
*
* @param message The message to use.
*/
public MapperException(String message)
{
super(message);
}
/**
* Constructs a MapperException with the specified cause.
* @param t the cause
*/
public MapperException(Throwable t) {
super(t);
}
/**
* Constructs a MapperException object using the specified String as a message, and the
* specified Throwable as a nested exception.
*
* @param message The message to use.
* @param t The exception to nest within this exception.
*/
public MapperException(String message, Throwable t)
{
super(message + "[" + t + "]", t);
}
}

View File

@ -0,0 +1,887 @@
package com.moparisthebest.jdbc;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
public class NullQueryMapper extends QueryMapper {
protected final boolean verbose;
protected final QueryMapper delegate;
private NullQueryMapper(Connection conn, String jndiName, QueryMapper delegate, ResultSetMapper cm, boolean verbose) {
this.verbose = verbose;
this.delegate = delegate == null ? new QueryMapper(conn, jndiName, cm) : delegate;
}
public NullQueryMapper(QueryMapper delegate, boolean verbose) {
this(null, null, delegate, null, verbose);
}
public NullQueryMapper(QueryMapper delegate) {
this(null, null, delegate, null, true);
}
public NullQueryMapper(Connection conn, boolean verbose) {
this(conn, null, null, null, verbose);
}
public NullQueryMapper(Connection conn, ResultSetMapper cm, boolean verbose) {
this(conn, null, null, cm, verbose);
}
public NullQueryMapper(Connection conn) {
this(conn, true);
}
public NullQueryMapper(Connection conn, ResultSetMapper cm) {
this(conn, cm, true);
}
public NullQueryMapper(String jndiName, boolean verbose) {
this(null, jndiName, null, null, verbose);
}
public NullQueryMapper(String jndiName, ResultSetMapper cm, boolean verbose) {
this(null, jndiName, null, cm, verbose);
}
public NullQueryMapper(String jndiName) {
this(jndiName, true);
}
public NullQueryMapper(String jndiName, ResultSetMapper cm) {
this(jndiName, cm, true);
}
// these update the database
@Override
public int executeUpdate(PreparedStatement ps, Object... bindObjects) {
try {
return delegate.executeUpdate(ps, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return -1;
}
@Override
public boolean executeUpdateSuccess(PreparedStatement ps, Object... bindObjects) {
try {
return delegate.executeUpdateSuccess(ps, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return false;
}
@Override
public int executeUpdate(String sql, Object... bindObjects) {
try {
return delegate.executeUpdate(sql, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return -1;
}
@Override
public boolean executeUpdateSuccess(String sql, Object... bindObjects) {
try {
return delegate.executeUpdateSuccess(sql, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return false;
}
// these update the database using UpdateableDTOs
@Override
public int updateRows(UpdateableDTO dto) {
try {
return delegate.updateRows(dto);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return -1;
}
@Override
public int updateRows(Collection<UpdateableDTO> dtos) {
try {
return delegate.updateRows(dtos);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return -1;
}
@Override
public int updateRows(UpdateableDTO[] dtos) {
try {
return delegate.updateRows(dtos);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return -1;
}
@Override
public int insertRows(UpdateableDTO dto) {
try {
return delegate.insertRows(dto);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return -1;
}
@Override
public int insertRows(Collection<UpdateableDTO> dtos) {
try {
return delegate.insertRows(dtos);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return -1;
}
@Override
public int insertRows(UpdateableDTO[] dtos) {
try {
return delegate.insertRows(dtos);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return -1;
}
// these grab ResultSets from the database
@Override
public ResultSet toResultSet(PreparedStatement ps, Object... bindObjects) {
try {
return delegate.toResultSet(ps, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public ResultSet toResultSet(String sql, Object... bindObjects) {
try {
return delegate.toResultSet(sql, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
// these are standard getters
@Override
public ResultSetMapper getCustomResultSetMapper() {
return delegate.getCustomResultSetMapper();
}
@Override
public Connection getConnection() {
return delegate.getConnection();
}
// these just delegate and change no functionality
@Override
public void close() {
delegate.close();
}
@Override
protected PreparedStatement bind(PreparedStatement ps, Object... bindObjects) throws SQLException {
return delegate.bind(ps, bindObjects);
}
@Override
protected ResultSet bindExecute(PreparedStatement ps, Object... bindObjects) throws SQLException {
return delegate.bindExecute(ps, bindObjects);
}
// and these are standard
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
NullQueryMapper that = (NullQueryMapper) o;
if (verbose != that.verbose) return false;
if (delegate != null ? !delegate.equals(that.delegate) : that.delegate != null) return false;
return true;
}
@Override
public int hashCode() {
int result = (verbose ? 1 : 0);
result = 31 * result + (delegate != null ? delegate.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "NullQueryMapper{" +
"verbose=" + verbose +
", delegate=" + delegate +
"}";
}
// DO NOT EDIT BELOW THIS LINE, OR CHANGE THIS COMMENT, CODE AUTOMATICALLY GENERATED BY genQueryMapper.sh
@Override
public <T> T toObject(PreparedStatement query, Class<T> componentType, final Object... bindObjects) {
try {
return delegate.toObject(query, componentType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T> T toObject(String query, Class<T> componentType, final Object... bindObjects) {
try {
return delegate.toObject(query, componentType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<String, V>, V> Map<String, V> toSingleMap(PreparedStatement query, Class<T> componentType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toSingleMap(query, componentType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<String, V>, V> Map<String, V> toSingleMap(String query, Class<T> componentType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toSingleMap(query, componentType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <V> Map<String, V> toSingleMap(PreparedStatement query, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toSingleMap(query, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <V> Map<String, V> toSingleMap(String query, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toSingleMap(query, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Collection<E>, E> T toCollection(PreparedStatement query, final Class<T> collectionType, Class<E> componentType, final Object... bindObjects) {
try {
return delegate.toCollection(query, collectionType, componentType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Collection<E>, E> T toCollection(String query, final Class<T> collectionType, Class<E> componentType, final Object... bindObjects) {
try {
return delegate.toCollection(query, collectionType, componentType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Collection<E>, E> T toCollection(PreparedStatement query, T list, Class<E> componentType, final Object... bindObjects) {
try {
return delegate.toCollection(query, list, componentType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Collection<E>, E> T toCollection(String query, T list, Class<E> componentType, final Object... bindObjects) {
try {
return delegate.toCollection(query, list, componentType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<K, E>, K, E> T toMap(PreparedStatement query, final Class<T> returnType, Class<K> mapKeyType, Class<E> componentType, final Object... bindObjects) {
try {
return delegate.toMap(query, returnType, mapKeyType, componentType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<K, E>, K, E> T toMap(String query, final Class<T> returnType, Class<K> mapKeyType, Class<E> componentType, final Object... bindObjects) {
try {
return delegate.toMap(query, returnType, mapKeyType, componentType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<K, E>, K, E> T toMap(PreparedStatement query, T map, Class<K> mapKeyType, Class<E> componentType, final Object... bindObjects) {
try {
return delegate.toMap(query, map, mapKeyType, componentType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<K, E>, K, E> T toMap(String query, T map, Class<K> mapKeyType, Class<E> componentType, final Object... bindObjects) {
try {
return delegate.toMap(query, map, mapKeyType, componentType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<K, E>, K, E extends Collection<C>, C> T toMapCollection(PreparedStatement query, final Class<T> returnType, Class<K> mapKeyType, Class<E> collectionType, Class<C> componentType, final Object... bindObjects) {
try {
return delegate.toMapCollection(query, returnType, mapKeyType, collectionType, componentType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<K, E>, K, E extends Collection<C>, C> T toMapCollection(String query, final Class<T> returnType, Class<K> mapKeyType, Class<E> collectionType, Class<C> componentType, final Object... bindObjects) {
try {
return delegate.toMapCollection(query, returnType, mapKeyType, collectionType, componentType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<K, E>, K, E extends Collection<C>, C> T toMapCollection(PreparedStatement query, T map, Class<K> mapKeyType, Class<E> collectionType, Class<C> componentType, final Object... bindObjects) {
try {
return delegate.toMapCollection(query, map, mapKeyType, collectionType, componentType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<K, E>, K, E extends Collection<C>, C> T toMapCollection(String query, T map, Class<K> mapKeyType, Class<E> collectionType, Class<C> componentType, final Object... bindObjects) {
try {
return delegate.toMapCollection(query, map, mapKeyType, collectionType, componentType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T> ListIterator<T> toListIterator(PreparedStatement query, final Class<T> type, final Object... bindObjects) {
try {
return delegate.toListIterator(query, type, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T> ListIterator<T> toListIterator(String query, final Class<T> type, final Object... bindObjects) {
try {
return delegate.toListIterator(query, type, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T> Iterator<T> toIterator(PreparedStatement query, final Class<T> type, final Object... bindObjects) {
try {
return delegate.toIterator(query, type, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T> Iterator<T> toIterator(String query, final Class<T> type, final Object... bindObjects) {
try {
return delegate.toIterator(query, type, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T> T[] toArray(PreparedStatement query, final Class<T> type, final Object... bindObjects) {
try {
return delegate.toArray(query, type, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T> T[] toArray(String query, final Class<T> type, final Object... bindObjects) {
try {
return delegate.toArray(query, type, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <E> List<E> toList(PreparedStatement query, Class<E> componentType, final Object... bindObjects) {
try {
return delegate.toList(query, componentType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <E> List<E> toList(String query, Class<E> componentType, final Object... bindObjects) {
try {
return delegate.toList(query, componentType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <K, E> Map<K, E> toMap(PreparedStatement query, Class<K> mapKeyType, Class<E> componentType, final Object... bindObjects) {
try {
return delegate.toMap(query, mapKeyType, componentType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <K, E> Map<K, E> toMap(String query, Class<K> mapKeyType, Class<E> componentType, final Object... bindObjects) {
try {
return delegate.toMap(query, mapKeyType, componentType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <K, E extends List<C>, C> Map<K, E> toMapList(PreparedStatement query, Class<K> mapKeyType, Class<C> componentType, final Object... bindObjects) {
try {
return delegate.toMapList(query, mapKeyType, componentType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <K, E extends List<C>, C> Map<K, E> toMapList(String query, Class<K> mapKeyType, Class<C> componentType, final Object... bindObjects) {
try {
return delegate.toMapList(query, mapKeyType, componentType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Collection<E>, E extends Map<String, V>, V> T toCollectionMap(PreparedStatement query, final Class<T> collectionType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toCollectionMap(query, collectionType, componentType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Collection<E>, E extends Map<String, V>, V> T toCollectionMap(String query, final Class<T> collectionType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toCollectionMap(query, collectionType, componentType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Collection<E>, E extends Map<String, V>, V> T toCollectionMap(PreparedStatement query, T list, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toCollectionMap(query, list, componentType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Collection<E>, E extends Map<String, V>, V> T toCollectionMap(String query, T list, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toCollectionMap(query, list, componentType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<K, E>, K, E extends Map<String, V>, V> T toMapMap(PreparedStatement query, final Class<T> returnType, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toMapMap(query, returnType, mapKeyType, componentType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<K, E>, K, E extends Map<String, V>, V> T toMapMap(String query, final Class<T> returnType, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toMapMap(query, returnType, mapKeyType, componentType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<K, E>, K, E extends Map<String, V>, V> T toMapMap(PreparedStatement query, T map, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toMapMap(query, map, mapKeyType, componentType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<K, E>, K, E extends Map<String, V>, V> T toMapMap(String query, T map, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toMapMap(query, map, mapKeyType, componentType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<K, C>, K, C extends Collection<E>, E extends Map<String, V>, V> T toMapCollectionMap(PreparedStatement query, final Class<T> returnType, Class<K> mapKeyType, Class<C> collectionType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toMapCollectionMap(query, returnType, mapKeyType, collectionType, componentType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<K, C>, K, C extends Collection<E>, E extends Map<String, V>, V> T toMapCollectionMap(String query, final Class<T> returnType, Class<K> mapKeyType, Class<C> collectionType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toMapCollectionMap(query, returnType, mapKeyType, collectionType, componentType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<K, C>, K, C extends Collection<E>, E extends Map<String, V>, V> T toMapCollectionMap(PreparedStatement query, T map, Class<K> mapKeyType, Class<C> collectionType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toMapCollectionMap(query, map, mapKeyType, collectionType, componentType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<K, C>, K, C extends Collection<E>, E extends Map<String, V>, V> T toMapCollectionMap(String query, T map, Class<K> mapKeyType, Class<C> collectionType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toMapCollectionMap(query, map, mapKeyType, collectionType, componentType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<String, V>, V> ListIterator<Map<String, V>> toListIteratorMap(PreparedStatement query, final Class<T> type, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toListIteratorMap(query, type, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<String, V>, V> ListIterator<Map<String, V>> toListIteratorMap(String query, final Class<T> type, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toListIteratorMap(query, type, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<String, V>, V> Iterator<Map<String, V>> toIteratorMap(PreparedStatement query, final Class<T> type, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toIteratorMap(query, type, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<String, V>, V> Iterator<Map<String, V>> toIteratorMap(String query, final Class<T> type, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toIteratorMap(query, type, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<String, V>, V> Map<String, V>[] toArrayMap(PreparedStatement query, final Class<T> type, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toArrayMap(query, type, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <T extends Map<String, V>, V> Map<String, V>[] toArrayMap(String query, final Class<T> type, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toArrayMap(query, type, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <E extends Map<String, V>, V> List<Map<String, V>> toListMap(PreparedStatement query, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toListMap(query, componentType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <E extends Map<String, V>, V> List<Map<String, V>> toListMap(String query, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toListMap(query, componentType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <K, E extends Map<String, V>, V> Map<K, Map<String, V>> toMapMap(PreparedStatement query, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toMapMap(query, mapKeyType, componentType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <K, E extends Map<String, V>, V> Map<K, Map<String, V>> toMapMap(String query, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toMapMap(query, mapKeyType, componentType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <K, E extends Map<String, V>, V> Map<K, List<Map<String, V>>> toMapListMap(PreparedStatement query, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toMapListMap(query, mapKeyType, componentType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <K, E extends Map<String, V>, V> Map<K, List<Map<String, V>>> toMapListMap(String query, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toMapListMap(query, mapKeyType, componentType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <V> ListIterator<Map<String, V>> toListIteratorMap(PreparedStatement query, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toListIteratorMap(query, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <V> ListIterator<Map<String, V>> toListIteratorMap(String query, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toListIteratorMap(query, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <V> Iterator<Map<String, V>> toIteratorMap(PreparedStatement query, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toIteratorMap(query, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <V> Iterator<Map<String, V>> toIteratorMap(String query, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toIteratorMap(query, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <V> List<Map<String, V>> toListMap(PreparedStatement query, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toListMap(query, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <V> List<Map<String, V>> toListMap(String query, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toListMap(query, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <K, V> Map<K, Map<String, V>> toMapMap(PreparedStatement query, Class<K> mapKeyType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toMapMap(query, mapKeyType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <K, V> Map<K, Map<String, V>> toMapMap(String query, Class<K> mapKeyType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toMapMap(query, mapKeyType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <K, V> Map<K, List<Map<String, V>>> toMapListMap(PreparedStatement query, Class<K> mapKeyType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toMapListMap(query, mapKeyType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
@Override
public <K, V> Map<K, List<Map<String, V>>> toMapListMap(String query, Class<K> mapKeyType, Class<V> mapValType, final Object... bindObjects) {
try {
return delegate.toMapListMap(query, mapKeyType, mapValType, bindObjects);
} catch (Throwable e) {
if (verbose) e.printStackTrace();
}
return null;
}
}

View File

@ -0,0 +1,780 @@
package com.moparisthebest.jdbc;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import java.io.*;
import java.sql.*;
import java.util.*;
import static com.moparisthebest.jdbc.TryClose.tryClose;
public class QueryMapper implements Closeable {
protected final ResultSetMapper cm;
protected final Connection conn;
protected final Context context;
protected QueryMapper(Connection conn, String jndiName, ResultSetMapper cm) {
this.cm = cm == null ? new ResultSetMapper() : cm;
Context context = null;
if (conn == null && jndiName != null)
try {
//todo: EnsureContext.setup();
context = new InitialContext();
DataSource ds = (DataSource) context.lookup(jndiName);
conn = ds.getConnection();
} catch (Throwable e) {
e.printStackTrace();
tryClose(conn);
tryClose(context);
}
this.conn = conn;
this.context = context;
if (this.conn == null)
throw new NullPointerException("Connection needs to be non-null for QueryMapper...");
}
public QueryMapper(Connection conn, ResultSetMapper cm) {
this(conn, null, cm);
}
public QueryMapper(Connection conn) {
this(conn, null);
}
public QueryMapper(String jndiName, ResultSetMapper cm) {
this(null, jndiName, cm);
}
public QueryMapper(String jndiName) {
this(jndiName, null);
}
/**
* Only meant to be called by implementing classes
*/
protected QueryMapper() {
this.cm = null;
this.conn = null;
this.context = null;
}
@Override
public void close() {
if (context != null) {
tryClose(conn);
tryClose(context);
}
}
private static class StringWrapper {
public final String s;
private StringWrapper(String s) {
this.s = s;
}
public String toString() {
return s;
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof StringWrapper)) return false;
StringWrapper that = (StringWrapper) o;
return !(s != null ? !s.equals(that.s) : that.s != null);
}
public int hashCode() {
return s != null ? s.hashCode() : 0;
}
}
private static class ClobString extends StringWrapper {
private ClobString(String s) {
super(s);
}
}
private static class BlobString extends StringWrapper {
private BlobString(String s) {
super(s);
}
}
public static Object wrapClob(String s) {
return new ClobString(s);
}
public static Object wrapBlob(String s) {
return new BlobString(s);
}
public static void setObject(final PreparedStatement ps, final int index, final Object o) throws SQLException {
// we are going to put most common ones up top so it should execute faster normally
if (o == null || o instanceof String || o instanceof Number)
ps.setObject(index, o);
// java.util.Date support, put it in a Timestamp
else if (o instanceof java.util.Date)
ps.setObject(index, o.getClass().equals(java.util.Date.class) ? new java.sql.Timestamp(((java.util.Date)o).getTime()) : o);
// CLOB support
else if (o instanceof Reader)
ps.setClob(index, (Reader) o);
else if (o instanceof ClobString)
ps.setObject(index, ((ClobString) o).s == null ? null : ((ClobString) o).s);
else if (o instanceof Clob)
ps.setClob(index, (Clob) o);
// BLOB support
else if (o instanceof byte[])
ps.setBlob(index, new ByteArrayInputStream((byte[]) o));
else if (o instanceof InputStream)
ps.setBlob(index, (InputStream) o);
else if (o instanceof File)
try {
ps.setBlob(index, new FileInputStream((File) o));
} catch (FileNotFoundException e) {
throw new SQLException("File to Blob FileNotFoundException", e);
}
else if (o instanceof BlobString)
try {
ps.setBlob(index, ((BlobString) o).s == null ? null : new ByteArrayInputStream(((BlobString) o).s.getBytes("UTF-8")));
} catch (UnsupportedEncodingException e) {
throw new SQLException("String to Blob UnsupportedEncodingException", e);
}
else if (o instanceof Blob)
ps.setBlob(index, (Blob) o);
else
ps.setObject(index, o); // probably won't get here ever, but just in case...
/*
switch(ps.getParameterMetaData().getParameterType(index)){ // 'java.sql.SQLException: Unsupported feature', fully JDBC 3.0 compliant my ass, freaking oracle...
case Types.CLOB:
if(o instanceof String)
ps.setObject(index, o);
else if (o instanceof Reader)
ps.setClob(index, (Reader) o);
else if (o instanceof Clob)
ps.setClob(index, (Clob) o);
return;
case Types.BLOB:
if (o instanceof byte[])
ps.setBlob(index, new ByteArrayInputStream((byte[])o));
else if (o instanceof InputStream)
ps.setBlob(index, (InputStream) o);
else if (o instanceof File)
try {
ps.setBlob(index, new FileInputStream((File) o));
} catch (FileNotFoundException e) {
throw new SQLException("File to Blob FileNotFoundException", e);
}
else if (o instanceof Blob)
ps.setBlob(index, (Blob) o);
else if(o instanceof String)
try{
ps.setBlob(index, new ByteArrayInputStream(((String) o).getBytes("UTF-8")));
}catch(UnsupportedEncodingException e){
throw new SQLException("String to Blob UnsupportedEncodingException", e);
}
return;
default:
ps.setObject(index, o);
}
*/
}
public static int recursiveBind(final PreparedStatement ps, final Object... bindObjects) throws SQLException {
return recursiveBind(ps, 0, bindObjects);
}
private static int recursiveBind(final PreparedStatement ps, int index, final Object... bindObjects) throws SQLException {
if (bindObjects != null && bindObjects.length > 0) {
for (Object o : bindObjects) {
if (o != null) {
if (o instanceof Object[]) {
index = recursiveBind(ps, index, (Object[]) o);
continue;
} else if (o instanceof Collection) {
index = recursiveBind(ps, index, ((Collection) o).toArray());
continue;
}
}
//System.out.printf("index: '%d' bound to '%s'\n", index+1, o);
setObject(ps, ++index, o);
//ps.setObject(++index, o);
}
}
return index;
}
public static PreparedStatement bindStatement(final PreparedStatement ps, final Object... bindObjects) throws SQLException {
recursiveBind(ps, bindObjects);
return ps;
}
protected PreparedStatement bind(final PreparedStatement ps, final Object... bindObjects) throws SQLException {
return bindStatement(ps, bindObjects);
}
protected ResultSet bindExecute(final PreparedStatement ps, final Object... bindObjects) throws SQLException {
return bind(ps, bindObjects).executeQuery();
}
// these update the database
public int executeUpdate(PreparedStatement ps, final Object... bindObjects) throws SQLException {
return bind(ps, bindObjects).executeUpdate();
}
public boolean executeUpdateSuccess(PreparedStatement ps, final Object... bindObjects) throws SQLException {
return this.executeUpdate(ps, bindObjects) >= 0;
}
public int executeUpdate(String sql, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.executeUpdate(ps, bindObjects);
} finally {
tryClose(ps);
}
}
public boolean executeUpdateSuccess(String sql, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.executeUpdateSuccess(ps, bindObjects);
} finally {
tryClose(ps);
}
}
// these update the database using UpdateableDTOs
public int updateRows(UpdateableDTO dto) throws SQLException {
return dto.updateRow(this);
}
public int updateRows(Collection<UpdateableDTO> dtos) throws SQLException {
int count = 0;
if (dtos != null)
for (UpdateableDTO dto : dtos)
count += dto.updateRow(this);
return count;
}
public int updateRows(UpdateableDTO[] dtos) throws SQLException {
return updateRows(Arrays.asList(dtos));
}
public int insertRows(UpdateableDTO dto) throws SQLException {
return dto.insertRow(this);
}
public int insertRows(Collection<UpdateableDTO> dtos) throws SQLException {
int count = 0;
if (dtos != null)
for (UpdateableDTO dto : dtos)
count += dto.insertRow(this);
return count;
}
public int insertRows(UpdateableDTO[] dtos) throws SQLException {
return insertRows(Arrays.asList(dtos));
}
// these grab ResultSets from the database
public ResultSet toResultSet(PreparedStatement ps, final Object... bindObjects) throws SQLException {
return toResultSet(ps, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, bindObjects);
}
public ResultSet toResultSet(PreparedStatement ps, int rsType, int rsConcurrency, final Object... bindObjects) throws SQLException {
return bindExecute(ps, bindObjects);
}
public ResultSet toResultSet(String sql, final Object... bindObjects) throws SQLException {
return toResultSet(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, bindObjects);
}
public ResultSet toResultSet(String sql, Integer rsType, Integer rsConcurrency, final Object... bindObjects) throws SQLException {
//throw new UnsupportedOperationException("Can't return ResultSet from String because the PreparedStatement can't be closed before the ResultSet is, so CachingQueryMapper will work.");
// works with StatementClosingResultSet
boolean error = true;
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = conn.prepareStatement(sql, rsType.intValue(), rsConcurrency.intValue());
rs = this.toResultSet(ps, bindObjects);
error = false;
return new StatementClosingResultSet(rs, ps);
} finally {
if (error) {
tryClose(rs);
tryClose(ps);
}
}
}
// these are standard getters
public ResultSetMapper getCustomResultSetMapper() {
return cm;
}
public Connection getConnection() {
return conn;
}
// DO NOT EDIT BELOW THIS LINE, OR CHANGE THIS COMMENT, CODE AUTOMATICALLY GENERATED BY genQueryMapper.sh
public <T> T toObject(PreparedStatement ps, Class<T> componentType, final Object... bindObjects) throws SQLException {
return cm.toObject(bindExecute(ps, bindObjects), componentType);
}
public <T> T toObject(String sql, Class<T> componentType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toObject(ps, componentType, bindObjects);
} finally {
tryClose(ps);
}
}
public <T extends Map<String, V>, V> Map<String, V> toSingleMap(PreparedStatement ps, Class<T> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return cm.toSingleMap(bindExecute(ps, bindObjects), componentType, mapValType);
}
public <T extends Map<String, V>, V> Map<String, V> toSingleMap(String sql, Class<T> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toSingleMap(ps, componentType, mapValType, bindObjects);
} finally {
tryClose(ps);
}
}
public <V> Map<String, V> toSingleMap(PreparedStatement ps, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return cm.toSingleMap(bindExecute(ps, bindObjects), mapValType);
}
public <V> Map<String, V> toSingleMap(String sql, Class<V> mapValType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toSingleMap(ps, mapValType, bindObjects);
} finally {
tryClose(ps);
}
}
public <T extends Collection<E>, E> T toCollection(PreparedStatement ps, final Class<T> collectionType, Class<E> componentType, final Object... bindObjects) throws SQLException {
return cm.toCollection(bindExecute(ps, bindObjects), collectionType, componentType);
}
public <T extends Collection<E>, E> T toCollection(String sql, final Class<T> collectionType, Class<E> componentType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toCollection(ps, collectionType, componentType, bindObjects);
} finally {
tryClose(ps);
}
}
public <T extends Collection<E>, E> T toCollection(PreparedStatement ps, T list, Class<E> componentType, final Object... bindObjects) throws SQLException {
return cm.toCollection(bindExecute(ps, bindObjects), list, componentType);
}
public <T extends Collection<E>, E> T toCollection(String sql, T list, Class<E> componentType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toCollection(ps, list, componentType, bindObjects);
} finally {
tryClose(ps);
}
}
public <T extends Map<K, E>, K, E> T toMap(PreparedStatement ps, final Class<T> returnType, Class<K> mapKeyType, Class<E> componentType, final Object... bindObjects) throws SQLException {
return cm.toMap(bindExecute(ps, bindObjects), returnType, mapKeyType, componentType);
}
public <T extends Map<K, E>, K, E> T toMap(String sql, final Class<T> returnType, Class<K> mapKeyType, Class<E> componentType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toMap(ps, returnType, mapKeyType, componentType, bindObjects);
} finally {
tryClose(ps);
}
}
public <T extends Map<K, E>, K, E> T toMap(PreparedStatement ps, T map, Class<K> mapKeyType, Class<E> componentType, final Object... bindObjects) throws SQLException {
return cm.toMap(bindExecute(ps, bindObjects), map, mapKeyType, componentType);
}
public <T extends Map<K, E>, K, E> T toMap(String sql, T map, Class<K> mapKeyType, Class<E> componentType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toMap(ps, map, mapKeyType, componentType, bindObjects);
} finally {
tryClose(ps);
}
}
public <T extends Map<K, E>, K, E extends Collection<C>, C> T toMapCollection(PreparedStatement ps, final Class<T> returnType, Class<K> mapKeyType, Class<E> collectionType, Class<C> componentType, final Object... bindObjects) throws SQLException {
return cm.toMapCollection(bindExecute(ps, bindObjects), returnType, mapKeyType, collectionType, componentType);
}
public <T extends Map<K, E>, K, E extends Collection<C>, C> T toMapCollection(String sql, final Class<T> returnType, Class<K> mapKeyType, Class<E> collectionType, Class<C> componentType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toMapCollection(ps, returnType, mapKeyType, collectionType, componentType, bindObjects);
} finally {
tryClose(ps);
}
}
public <T extends Map<K, E>, K, E extends Collection<C>, C> T toMapCollection(PreparedStatement ps, T map, Class<K> mapKeyType, Class<E> collectionType, Class<C> componentType, final Object... bindObjects) throws SQLException {
return cm.toMapCollection(bindExecute(ps, bindObjects), map, mapKeyType, collectionType, componentType);
}
public <T extends Map<K, E>, K, E extends Collection<C>, C> T toMapCollection(String sql, T map, Class<K> mapKeyType, Class<E> collectionType, Class<C> componentType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toMapCollection(ps, map, mapKeyType, collectionType, componentType, bindObjects);
} finally {
tryClose(ps);
}
}
public <T> ListIterator<T> toListIterator(PreparedStatement ps, final Class<T> type, final Object... bindObjects) throws SQLException {
return cm.toListIterator(bindExecute(ps, bindObjects), type);
}
public <T> ListIterator<T> toListIterator(String sql, final Class<T> type, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toListIterator(ps, type, bindObjects);
} finally {
tryClose(ps);
}
}
public <T> Iterator<T> toIterator(PreparedStatement ps, final Class<T> type, final Object... bindObjects) throws SQLException {
return cm.toIterator(bindExecute(ps, bindObjects), type);
}
public <T> Iterator<T> toIterator(String sql, final Class<T> type, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toIterator(ps, type, bindObjects);
} finally {
tryClose(ps);
}
}
public <T> T[] toArray(PreparedStatement ps, final Class<T> type, final Object... bindObjects) throws SQLException {
return cm.toArray(bindExecute(ps, bindObjects), type);
}
public <T> T[] toArray(String sql, final Class<T> type, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toArray(ps, type, bindObjects);
} finally {
tryClose(ps);
}
}
public <E> List<E> toList(PreparedStatement ps, Class<E> componentType, final Object... bindObjects) throws SQLException {
return cm.toList(bindExecute(ps, bindObjects), componentType);
}
public <E> List<E> toList(String sql, Class<E> componentType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toList(ps, componentType, bindObjects);
} finally {
tryClose(ps);
}
}
public <K, E> Map<K, E> toMap(PreparedStatement ps, Class<K> mapKeyType, Class<E> componentType, final Object... bindObjects) throws SQLException {
return cm.toMap(bindExecute(ps, bindObjects), mapKeyType, componentType);
}
public <K, E> Map<K, E> toMap(String sql, Class<K> mapKeyType, Class<E> componentType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toMap(ps, mapKeyType, componentType, bindObjects);
} finally {
tryClose(ps);
}
}
public <K, E extends List<C>, C> Map<K, E> toMapList(PreparedStatement ps, Class<K> mapKeyType, Class<C> componentType, final Object... bindObjects) throws SQLException {
return cm.toMapList(bindExecute(ps, bindObjects), mapKeyType, componentType);
}
public <K, E extends List<C>, C> Map<K, E> toMapList(String sql, Class<K> mapKeyType, Class<C> componentType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toMapList(ps, mapKeyType, componentType, bindObjects);
} finally {
tryClose(ps);
}
}
public <T extends Collection<E>, E extends Map<String, V>, V> T toCollectionMap(PreparedStatement ps, final Class<T> collectionType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return cm.toCollectionMap(bindExecute(ps, bindObjects), collectionType, componentType, mapValType);
}
public <T extends Collection<E>, E extends Map<String, V>, V> T toCollectionMap(String sql, final Class<T> collectionType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toCollectionMap(ps, collectionType, componentType, mapValType, bindObjects);
} finally {
tryClose(ps);
}
}
public <T extends Collection<E>, E extends Map<String, V>, V> T toCollectionMap(PreparedStatement ps, T list, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return cm.toCollectionMap(bindExecute(ps, bindObjects), list, componentType, mapValType);
}
public <T extends Collection<E>, E extends Map<String, V>, V> T toCollectionMap(String sql, T list, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toCollectionMap(ps, list, componentType, mapValType, bindObjects);
} finally {
tryClose(ps);
}
}
public <T extends Map<K, E>, K, E extends Map<String, V>, V> T toMapMap(PreparedStatement ps, final Class<T> returnType, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return cm.toMapMap(bindExecute(ps, bindObjects), returnType, mapKeyType, componentType, mapValType);
}
public <T extends Map<K, E>, K, E extends Map<String, V>, V> T toMapMap(String sql, final Class<T> returnType, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toMapMap(ps, returnType, mapKeyType, componentType, mapValType, bindObjects);
} finally {
tryClose(ps);
}
}
public <T extends Map<K, E>, K, E extends Map<String, V>, V> T toMapMap(PreparedStatement ps, T map, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return cm.toMapMap(bindExecute(ps, bindObjects), map, mapKeyType, componentType, mapValType);
}
public <T extends Map<K, E>, K, E extends Map<String, V>, V> T toMapMap(String sql, T map, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toMapMap(ps, map, mapKeyType, componentType, mapValType, bindObjects);
} finally {
tryClose(ps);
}
}
public <T extends Map<K, C>, K, C extends Collection<E>, E extends Map<String, V>, V> T toMapCollectionMap(PreparedStatement ps, final Class<T> returnType, Class<K> mapKeyType, Class<C> collectionType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return cm.toMapCollectionMap(bindExecute(ps, bindObjects), returnType, mapKeyType, collectionType, componentType, mapValType);
}
public <T extends Map<K, C>, K, C extends Collection<E>, E extends Map<String, V>, V> T toMapCollectionMap(String sql, final Class<T> returnType, Class<K> mapKeyType, Class<C> collectionType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toMapCollectionMap(ps, returnType, mapKeyType, collectionType, componentType, mapValType, bindObjects);
} finally {
tryClose(ps);
}
}
public <T extends Map<K, C>, K, C extends Collection<E>, E extends Map<String, V>, V> T toMapCollectionMap(PreparedStatement ps, T map, Class<K> mapKeyType, Class<C> collectionType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return cm.toMapCollectionMap(bindExecute(ps, bindObjects), map, mapKeyType, collectionType, componentType, mapValType);
}
public <T extends Map<K, C>, K, C extends Collection<E>, E extends Map<String, V>, V> T toMapCollectionMap(String sql, T map, Class<K> mapKeyType, Class<C> collectionType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toMapCollectionMap(ps, map, mapKeyType, collectionType, componentType, mapValType, bindObjects);
} finally {
tryClose(ps);
}
}
public <T extends Map<String, V>, V> ListIterator<Map<String, V>> toListIteratorMap(PreparedStatement ps, final Class<T> type, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return cm.toListIteratorMap(bindExecute(ps, bindObjects), type, mapValType);
}
public <T extends Map<String, V>, V> ListIterator<Map<String, V>> toListIteratorMap(String sql, final Class<T> type, Class<V> mapValType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toListIteratorMap(ps, type, mapValType, bindObjects);
} finally {
tryClose(ps);
}
}
public <T extends Map<String, V>, V> Iterator<Map<String, V>> toIteratorMap(PreparedStatement ps, final Class<T> type, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return cm.toIteratorMap(bindExecute(ps, bindObjects), type, mapValType);
}
public <T extends Map<String, V>, V> Iterator<Map<String, V>> toIteratorMap(String sql, final Class<T> type, Class<V> mapValType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toIteratorMap(ps, type, mapValType, bindObjects);
} finally {
tryClose(ps);
}
}
public <T extends Map<String, V>, V> Map<String, V>[] toArrayMap(PreparedStatement ps, final Class<T> type, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return cm.toArrayMap(bindExecute(ps, bindObjects), type, mapValType);
}
public <T extends Map<String, V>, V> Map<String, V>[] toArrayMap(String sql, final Class<T> type, Class<V> mapValType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toArrayMap(ps, type, mapValType, bindObjects);
} finally {
tryClose(ps);
}
}
public <E extends Map<String, V>, V> List<Map<String, V>> toListMap(PreparedStatement ps, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return cm.toListMap(bindExecute(ps, bindObjects), componentType, mapValType);
}
public <E extends Map<String, V>, V> List<Map<String, V>> toListMap(String sql, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toListMap(ps, componentType, mapValType, bindObjects);
} finally {
tryClose(ps);
}
}
public <K, E extends Map<String, V>, V> Map<K, Map<String, V>> toMapMap(PreparedStatement ps, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return cm.toMapMap(bindExecute(ps, bindObjects), mapKeyType, componentType, mapValType);
}
public <K, E extends Map<String, V>, V> Map<K, Map<String, V>> toMapMap(String sql, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toMapMap(ps, mapKeyType, componentType, mapValType, bindObjects);
} finally {
tryClose(ps);
}
}
public <K, E extends Map<String, V>, V> Map<K, List<Map<String, V>>> toMapListMap(PreparedStatement ps, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return cm.toMapListMap(bindExecute(ps, bindObjects), mapKeyType, componentType, mapValType);
}
public <K, E extends Map<String, V>, V> Map<K, List<Map<String, V>>> toMapListMap(String sql, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toMapListMap(ps, mapKeyType, componentType, mapValType, bindObjects);
} finally {
tryClose(ps);
}
}
public <V> ListIterator<Map<String, V>> toListIteratorMap(PreparedStatement ps, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return cm.toListIteratorMap(bindExecute(ps, bindObjects), mapValType);
}
public <V> ListIterator<Map<String, V>> toListIteratorMap(String sql, Class<V> mapValType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toListIteratorMap(ps, mapValType, bindObjects);
} finally {
tryClose(ps);
}
}
public <V> Iterator<Map<String, V>> toIteratorMap(PreparedStatement ps, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return cm.toIteratorMap(bindExecute(ps, bindObjects), mapValType);
}
public <V> Iterator<Map<String, V>> toIteratorMap(String sql, Class<V> mapValType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toIteratorMap(ps, mapValType, bindObjects);
} finally {
tryClose(ps);
}
}
public <V> List<Map<String, V>> toListMap(PreparedStatement ps, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return cm.toListMap(bindExecute(ps, bindObjects), mapValType);
}
public <V> List<Map<String, V>> toListMap(String sql, Class<V> mapValType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toListMap(ps, mapValType, bindObjects);
} finally {
tryClose(ps);
}
}
public <K, V> Map<K, Map<String, V>> toMapMap(PreparedStatement ps, Class<K> mapKeyType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return cm.toMapMap(bindExecute(ps, bindObjects), mapKeyType, mapValType);
}
public <K, V> Map<K, Map<String, V>> toMapMap(String sql, Class<K> mapKeyType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toMapMap(ps, mapKeyType, mapValType, bindObjects);
} finally {
tryClose(ps);
}
}
public <K, V> Map<K, List<Map<String, V>>> toMapListMap(PreparedStatement ps, Class<K> mapKeyType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
return cm.toMapListMap(bindExecute(ps, bindObjects), mapKeyType, mapValType);
}
public <K, V> Map<K, List<Map<String, V>>> toMapListMap(String sql, Class<K> mapKeyType, Class<V> mapValType, final Object... bindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
return this.toMapListMap(ps, mapKeyType, mapValType, bindObjects);
} finally {
tryClose(ps);
}
}
}

View File

@ -0,0 +1,973 @@
package com.moparisthebest.jdbc;
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $Header:$
*/
import java.lang.ref.SoftReference;
import java.lang.reflect.*;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.*;
/**
* Default ResultSetMapper implementation for Objects.
* <p/>
* This class is heavily modified from org.apache.beehive.controls.system.jdbc.DefaultObjectResultSetMapper
* <p/>
* This uses CustomRowToObjectMapper to perform the actual mapping to individual classes, so look to that
* implementation for details.
* <p/>
* This supports mapping to a single object, or collections of Objects, currently it supports:
* 1. arrays
* 2. anything implementing java.util.Collection with a public no-arg constructor
* 3. anything implementing java.util.Map with a public no-arg constructor
* a. The first column in the ResultSet will be the Map's key
* b. If there are only two columns, the second will be the Map's value
* c. If there are more than two columns, the value will be mapped to an object with the entire ResultSet in it,
* including the key, just like returning a Collection would do
* 4. Iterators returned by a Collection, or ListIterators returned by a List
* <p/>
* It has sensible default implementations to return if you specify an interface, look in Map 'interfaceToConcrete'
* for the default values returned for specific interfaces. If not specified in there, Map's default is HashMap,
* while Collection's default is ArrayList.
* <p/>
* Anything else must be a concrete class with a public no-arg constructor to instantiate it
*
* @author Travis Burtrum (modifications from beehive)
*/
public class ResultSetMapper {
public static final Map<Class, Class> interfaceToConcrete = Collections.unmodifiableMap(new HashMap<Class, Class>() {{
// Collection's
put(Collection.class, ArrayList.class);
// List
put(List.class, ArrayList.class);
// Set's
put(Set.class, HashSet.class);
// SortedSet's
put(SortedSet.class, TreeSet.class);
put(NavigableSet.class, ConcurrentSkipListSet.class);
// Queue's
put(Queue.class, LinkedList.class);
put(Deque.class, LinkedList.class);
// BlockingQueue's
put(BlockingQueue.class, LinkedBlockingQueue.class);
put(BlockingDeque.class, LinkedBlockingDeque.class);
// Map's
put(Map.class, HashMap.class);
// ConcurrentMap's
put(ConcurrentMap.class, ConcurrentHashMap.class);
put(ConcurrentNavigableMap.class, ConcurrentSkipListMap.class);
// SortedMap's
put(SortedMap.class, TreeMap.class);
put(NavigableMap.class, TreeMap.class);
}});
@SuppressWarnings({"unchecked"})
public static <T, E> Class<? extends T> getConcreteClass(final Class<T> returnType, final Class<E> defaultConcreteClass) {
int classModifiers = returnType.getModifiers();
if (Modifier.isInterface(classModifiers) || Modifier.isAbstract(classModifiers)) {
Class<? extends T> concrete = (Class<? extends T>) interfaceToConcrete.get(returnType);
return concrete == null ? (Class<? extends T>) defaultConcreteClass : concrete;
}
return returnType;
}
public static <T, E> T instantiateClass(final Class<T> returnType, final Class<E> defaultConcreteClass) {
try {
return getConcreteClass(returnType, defaultConcreteClass).newInstance();
} catch (Throwable e) {
throw new MapperException("Failed to instantiate class of type " + returnType.getName(), e);
}
}
private final Calendar cal;
private final int arrayMaxLength;
public ResultSetMapper(Calendar cal, int arrayMaxLength) {
this.cal = cal;
this.arrayMaxLength = arrayMaxLength;
}
public ResultSetMapper() {
this(1024);
}
public ResultSetMapper(int arrayMaxLength) {
this(null, arrayMaxLength);
}
protected <T> T privToObject(ResultSet rs, Class<T> componentType, Calendar cal, Class<?> mapValType) {
T ret = null;
try {
if (rs.next())
ret = getRowMapper(rs, componentType, cal, mapValType).mapRowToReturnType();
} catch (SQLException e) {
// ignore
}
tryClose(rs);
return ret == null ? RowToObjectMapper.fixNull(componentType) : ret;
}
protected <T extends Collection<E>, E> T privToCollection(ResultSet rs, final Class<T> collectionType, Class<E> componentType, int arrayMaxLength, Calendar cal, Class<?> mapValType) {
return privToCollection(rs, instantiateClass(collectionType, ArrayList.class), componentType, arrayMaxLength, cal, mapValType);
}
/**
* Invoked when the return type of the method is an array type.
*
* @param rs ResultSet to process.
* @param componentType The class of object contained within the array
* @param arrayMaxLength The maximum size of array to create, a value of 0 indicates that the array
* size will be the same as the result set size (no limit).
* @param cal A calendar instance to use for date/time values
* @return An array of the specified class type
*/
protected <T extends Collection<E>, E> T privToCollection(ResultSet rs, T list, Class<E> componentType, int arrayMaxLength, Calendar cal, Class<?> mapValType) {
int numRows = 0;
// dereference list in an attempt to gracefully avoid OutOfMemoryError's
final SoftReference<T> softList = new SoftReference<T>(list);
list = null;
try {
// 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);
for (; (unlimitedRows || numRows != arrayMaxLength) && rs.next(); ++numRows) {
E object = rowMapper.mapRowToReturnType();
list = softList.get();
if (list == null)
throw new OutOfMemoryError();
list.add(object);
list = null;
}
if (!unlimitedRows)
warnOnMaxLength(numRows, arrayMaxLength, rs);
list = softList.get();
if (list == null)
throw new OutOfMemoryError();
// if this list is Finishable, call finish()
if (list instanceof Finishable)
((Finishable) list).finish(rs);
tryClose(rs);
return list;
} catch(OutOfMemoryError e){
tryClose(rs);
throw new MapperException(String.format("Too many rows (processed %d, max %d), ran out of memory.", numRows, arrayMaxLength), e);
} catch(Throwable e) {
if(list == null)
list = softList.get();
String columnName = "UNKNOWN";
String columnType = "UNKNOWN";
String returnedType = "UNKNOWN";
int badColumn = 0;
try {
ResultSetMetaData md = rs.getMetaData();
badColumn = e.getCause() instanceof SQLExceptionColumnNum ? ((SQLExceptionColumnNum)e.getCause()).getColumnNum() : 1;
columnName = md.getColumnName(badColumn);
columnType = md.getColumnTypeName(badColumn);
returnedType = ((list != null && !list.isEmpty()) ? list.iterator().next() : rs.getObject(badColumn)).getClass().getName();
} catch (Throwable t) {
// ignore
}
tryClose(rs);
// assuming no errors in resultSetObject() this can only happen
// for single column result sets.
throw new MapperException("The declared Java type for "
+ String.format("%s<%s>"
, (list != null ? list.getClass() : "UnknownCollection")
, getComponentName(componentType, mapValType))
+ " is incompatible with the SQL format of column " + badColumn + " '" + columnName
+ "' (" + columnType + ") which returns objects of type " + returnedType,
e);
}
}
protected <T extends Map<K, E>, K, E> T privToMap(ResultSet rs, final Class<T> returnType, Class<K> mapKeyType, Class<E> componentType, int arrayMaxLength, Calendar cal, Class<?> mapValType) {
return privToMap(rs, instantiateClass(returnType, HashMap.class), mapKeyType, componentType, arrayMaxLength, cal, mapValType);
}
/**
* Invoked when the return type of the method is a Map type.
*
* @param rs ResultSet to process.
* @param arrayMaxLength The maximum size of array to create, a value of 0 indicates that the array
* size will be the same as the result set size (no limit).
* @param cal A calendar instance to use for date/time values
* @return An array of the specified class type
*/
protected <T extends Map<K, E>, K, E> T privToMap(ResultSet rs, T map, Class<K> mapKeyType, Class<E> componentType, int arrayMaxLength, Calendar cal, Class<?> mapValType) {
int numRows = 0;
// dereference map in an attempt to gracefully avoid OutOfMemoryError's
final SoftReference<T> softMap = new SoftReference<T>(map);
map = null;
try {
// 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);
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();
map = softMap.get();
if (map == null)
throw new OutOfMemoryError();
map.put(key, value);
map = null;
}
if (!unlimitedRows)
warnOnMaxLength(numRows, arrayMaxLength, rs);
map = softMap.get();
if (map == null)
throw new OutOfMemoryError();
// if this map is Finishable, call finish()
if (map instanceof Finishable)
((Finishable) map).finish(rs);
tryClose(rs);
return map;
} catch(OutOfMemoryError e){
tryClose(rs);
throw new MapperException(String.format("Too many rows (processed %d, max %d), ran out of memory.", numRows, arrayMaxLength), e);
}catch (Throwable e) {
if(map == null)
map = softMap.get();
String columnName = "UNKNOWN";
String columnType = "UNKNOWN";
String returnedType = "UNKNOWN";
int badColumn = 0;
try {
ResultSetMetaData md = rs.getMetaData();
badColumn = e.getCause() instanceof SQLExceptionColumnNum ? ((SQLExceptionColumnNum)e.getCause()).getColumnNum() : 1;
columnName = md.getColumnName(badColumn);
columnType = md.getColumnTypeName(badColumn);
returnedType = ((map != null && !map.isEmpty()) ? map.values().iterator().next() : rs.getObject(badColumn)).getClass().getName();
} catch (Throwable t) {
// ignore
}
tryClose(rs);
// assuming no errors in resultSetObject() this can only happen
// for single column result sets.
throw new MapperException("The declared Java type for "
+ String.format("%s<%s, %s>"
, (map != null ? map.getClass() : "UnknownMap")
, mapKeyType != null ? mapKeyType.getName() : "UNKNOWN"
, getComponentName(componentType, mapValType))
+ " is incompatible with the SQL format of column "+ badColumn + " '" + columnName
+ "' (" + columnType + ") which returns objects of type " + returnedType,
e);
}
}
protected <T extends Map<K, E>, K, E extends Collection<C>, C> T privToMapCollection(ResultSet rs, final Class<T> returnType, Class<K> mapKeyType, Class<E> collectionType, Class<C> componentType, int arrayMaxLength, Calendar cal, Class<?> mapValType) {
return privToMapCollection(rs, instantiateClass(returnType, HashMap.class), mapKeyType, collectionType, componentType, arrayMaxLength, cal, mapValType);
}
/**
* Invoked when the return type of the method is a Map type with a list for a value.
*
* @param rs ResultSet to process.
* @param arrayMaxLength The maximum size of array to create, a value of 0 indicates that the array
* size will be the same as the result set size (no limit).
* @param cal A calendar instance to use for date/time values
* @return An array of the specified class type
*/
protected <T extends Map<K, E>, K, E extends Collection<C>, C> T privToMapCollection(ResultSet rs, T map, Class<K> mapKeyType, Class<E> collectionType, Class<C> componentType, int arrayMaxLength, Calendar cal, Class<?> mapValType) {
int numRows = 0;
// dereference map in an attempt to gracefully avoid OutOfMemoryError's
final SoftReference<T> softMap = new SoftReference<T>(map);
map = null;
try {
// 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);
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();
map = softMap.get();
if (map == null)
throw new OutOfMemoryError();
E list = map.get(key);
if(list == null){
list = instantiateClass(collectionType, ArrayList.class);
map.put(key, list);
}
list.add(value);
map = null;
}
if (!unlimitedRows)
warnOnMaxLength(numRows, arrayMaxLength, rs);
map = softMap.get();
if (map == null)
throw new OutOfMemoryError();
// if this map is Finishable, call finish()
if (map instanceof Finishable)
((Finishable) map).finish(rs);
tryClose(rs);
return map;
} catch(OutOfMemoryError e){
tryClose(rs);
throw new MapperException(String.format("Too many rows (processed %d, max %d), ran out of memory.", numRows, arrayMaxLength), e);
}catch (Throwable e) {
if(map == null)
map = softMap.get();
String columnName = "UNKNOWN";
String columnType = "UNKNOWN";
String returnedType = "UNKNOWN";
int badColumn = 0;
try {
ResultSetMetaData md = rs.getMetaData();
badColumn = e.getCause() instanceof SQLExceptionColumnNum ? ((SQLExceptionColumnNum)e.getCause()).getColumnNum() : 1;
columnName = md.getColumnName(badColumn);
columnType = md.getColumnTypeName(badColumn);
returnedType = ((map != null && !map.isEmpty()) ? map.values().iterator().next() : rs.getObject(badColumn)).getClass().getName();
} catch (Throwable t) {
// ignore
}
tryClose(rs);
// assuming no errors in resultSetObject() this can only happen
// for single column result sets.
throw new MapperException("The declared Java type for "
+ String.format("%s<%s, %s>"
, (map != null ? map.getClass() : "UnknownMap")
, mapKeyType != null ? mapKeyType.getName() : "UNKNOWN"
, getComponentName(componentType, mapValType))
+ " is incompatible with the SQL format of column "+ badColumn + " '" + columnName
+ "' (" + columnType + ") which returns objects of type " + returnedType,
e);
}
}
// methods using toMapCollection to return different types
protected <T> ListIterator<T> privToListIterator(ResultSet rs, final Class<T> type, int arrayMaxLength, Calendar cal, Class<?> mapValType) {
return privToList(rs, type, arrayMaxLength, cal, mapValType).listIterator();
}
protected <T> Iterator<T> privToIterator(ResultSet rs, final Class<T> type, int arrayMaxLength, Calendar cal, Class<?> mapValType) {
return privToList(rs, type, arrayMaxLength, cal, mapValType).iterator();
}
@SuppressWarnings({"unchecked"})
protected <T> T[] privToArray(ResultSet rs, final Class<T> type, int arrayMaxLength, Calendar cal, Class<?> mapValType) {
List<T> list = privToList(rs, type, arrayMaxLength, cal, mapValType);
return list.toArray((T[]) Array.newInstance(type, list.size()));
}
protected <E> List<E> privToList(ResultSet rs, Class<E> componentType, int arrayMaxLength, Calendar cal, Class<?> mapValType) {
return privToCollection(rs, new ArrayList<E>(), componentType, arrayMaxLength, cal, mapValType);
}
protected <K, E> Map<K, E> privToMap(ResultSet rs, Class<K> mapKeyType, Class<E> componentType, int arrayMaxLength, Calendar cal, Class<?> mapValType) {
return privToMap(rs, new HashMap<K, E>(), mapKeyType, componentType, arrayMaxLength, cal, mapValType);
}
protected <K, E extends Collection<C>, C> Map<K, E> privToMapCollection(ResultSet rs, Class<K> mapKeyType, Class<E> collectionType, Class<C> componentType, int arrayMaxLength, Calendar cal, Class<?> mapValType) {
return privToMapCollection(rs, new HashMap<K, E>(), mapKeyType, collectionType, componentType, arrayMaxLength, cal, mapValType);
}
// 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 void warnOnMaxLength(final int numRows, final int arrayMaxLength, final ResultSet rs) {
if (numRows < arrayMaxLength)
return;
int totalRows = numRows;
try {
if (rs.getType() != ResultSet.TYPE_FORWARD_ONLY) {
rs.last();
totalRows = rs.getRow();
} else {
totalRows = rs.getRow();
while (rs.next())
++totalRows;
}
if (totalRows == 0)
totalRows = numRows;
} catch (Throwable e) {
e.printStackTrace();
}
System.err.printf("This JdbcControl query returned %d rows, %s arrayMaxLength (%d), which you most likely never want to happen, investigate!!!!\n",
totalRows, totalRows == numRows ? "equaling" : "exceeding", arrayMaxLength);
Thread.dumpStack();
}
// overloaded helper methods
public <T> T toObject(ResultSet rs, Class<T> componentType, Calendar cal) {
return privToObject(rs, componentType, cal, null);
}
public <T extends Collection<E>, E> T toCollection(ResultSet rs, final Class<T> collectionType, Class<E> componentType, int arrayMaxLength, Calendar cal) {
return privToCollection(rs, collectionType, componentType, arrayMaxLength, cal, null);
}
public <T extends Collection<E>, E> T toCollection(ResultSet rs, T list, Class<E> componentType, int arrayMaxLength, Calendar cal) {
return privToCollection(rs, list, componentType, arrayMaxLength, cal, null);
}
public <T extends Map<K, E>, K, E> T toMap(ResultSet rs, final Class<T> returnType, Class<K> mapKeyType, Class<E> componentType, int arrayMaxLength, Calendar cal) {
return privToMap(rs, returnType, mapKeyType, componentType, arrayMaxLength, cal, null);
}
public <T extends Map<K, E>, K, E> T toMap(ResultSet rs, T map, Class<K> mapKeyType, Class<E> componentType, int arrayMaxLength, Calendar cal) {
return privToMap(rs, map, mapKeyType, componentType, arrayMaxLength, cal, null);
}
public <T extends Map<K, E>, K, E extends Collection<C>, C> T toMapCollection(ResultSet rs, final Class<T> returnType, Class<K> mapKeyType, Class<E> collectionType, Class<C> componentType, int arrayMaxLength, Calendar cal) {
return privToMapCollection(rs, returnType, mapKeyType, collectionType, componentType, arrayMaxLength, cal, null);
}
public <T extends Map<K, E>, K, E extends Collection<C>, C> T toMapCollection(ResultSet rs, T map, Class<K> mapKeyType, Class<E> collectionType, Class<C> componentType, int arrayMaxLength, Calendar cal) {
return privToMapCollection(rs, map, mapKeyType, collectionType, componentType, arrayMaxLength, cal, null);
}
public <T> ListIterator<T> toListIterator(ResultSet rs, final Class<T> type, int arrayMaxLength, Calendar cal) {
return privToListIterator(rs, type, arrayMaxLength, cal, null);
}
public <T> Iterator<T> toIterator(ResultSet rs, final Class<T> type, int arrayMaxLength, Calendar cal) {
return privToIterator(rs, type, arrayMaxLength, cal, null);
}
public <T> T[] toArray(ResultSet rs, final Class<T> type, int arrayMaxLength, Calendar cal) {
return privToArray(rs, type, arrayMaxLength, cal, null);
}
/**
* Returns a simple List of componentType
*/
public <E> List<E> toList(ResultSet rs, Class<E> componentType, int arrayMaxLength, Calendar cal) {
return privToList(rs, componentType, arrayMaxLength, cal, null);
}
/**
* Returns a simple Map of mapKeyType -> componentType
*/
public <K, E> Map<K, E> toMap(ResultSet rs, Class<K> mapKeyType, Class<E> componentType, int arrayMaxLength, Calendar cal) {
return privToMap(rs, mapKeyType, componentType, arrayMaxLength, cal, null);
}
/**
* Returns a simple Map of mapKeyType -> List<componentType>
*/
@SuppressWarnings({"unchecked"})
public <K, E extends List<C>, C> Map<K, E> toMapList(ResultSet rs, Class<K> mapKeyType, Class<C> componentType, int arrayMaxLength, Calendar cal) {
return (Map<K, E>) privToMapCollection(rs, mapKeyType, List.class, componentType, arrayMaxLength, cal, null);
}
// map methods
// the following 6 methods I can find no way to not require an unchecked cast on the object being returned
// please find a way and let me know, until then, I won't provide overloaded methods for them
public <T extends Collection<E>, E extends Map<String, V>, V> T toCollectionMap(ResultSet rs, final Class<T> collectionType, Class<E> componentType, Class<V> mapValType, int arrayMaxLength, Calendar cal) {
return privToCollection(rs, collectionType, componentType, arrayMaxLength, cal, mapValType);
}
public <T extends Collection<E>, E extends Map<String, V>, V> T toCollectionMap(ResultSet rs, T list, Class<E> componentType, Class<V> mapValType, int arrayMaxLength, Calendar cal) {
return privToCollection(rs, list, componentType, arrayMaxLength, cal, mapValType);
}
public <T extends Map<K, E>, K, E extends Map<String, V>, V> T toMapMap(ResultSet rs, final Class<T> returnType, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, int arrayMaxLength, Calendar cal) {
return privToMap(rs, returnType, mapKeyType, componentType, arrayMaxLength, cal, mapValType);
}
public <T extends Map<K, E>, K, E extends Map<String, V>, V> T toMapMap(ResultSet rs, T map, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, int arrayMaxLength, Calendar cal) {
return privToMap(rs, map, mapKeyType, componentType, arrayMaxLength, cal, mapValType);
}
public <T extends Map<K, C>, K, C extends Collection<E>, E extends Map<String, V>, V> T toMapCollectionMap(ResultSet rs, final Class<T> returnType, Class<K> mapKeyType, Class<C> collectionType, Class<E> componentType, Class<V> mapValType, int arrayMaxLength, Calendar cal) {
return privToMapCollection(rs, returnType, mapKeyType, collectionType, componentType, arrayMaxLength, cal, mapValType);
}
public <T extends Map<K, C>, K, C extends Collection<E>, E extends Map<String, V>, V> T toMapCollectionMap(ResultSet rs, T map, Class<K> mapKeyType, Class<C> collectionType, Class<E> componentType, Class<V> mapValType, int arrayMaxLength, Calendar cal) {
return privToMapCollection(rs, map, mapKeyType, collectionType, componentType, arrayMaxLength, cal, mapValType);
}
public <T extends Map<String, V>, V> Map<String, V> toSingleMap(ResultSet rs, Class<T> componentType, Class<V> mapValType, Calendar cal) {
return privToObject(rs, componentType, cal, mapValType);
}
@SuppressWarnings({"unchecked"})
public <T extends Map<String, V>, V> ListIterator<Map<String, V>> toListIteratorMap(ResultSet rs, final Class<T> type, Class<V> mapValType, int arrayMaxLength, Calendar cal) {
return (ListIterator<Map<String, V>>) privToListIterator(rs, type, arrayMaxLength, cal, mapValType);
}
@SuppressWarnings({"unchecked"})
public <T extends Map<String, V>, V> Iterator<Map<String, V>> toIteratorMap(ResultSet rs, final Class<T> type, Class<V> mapValType, int arrayMaxLength, Calendar cal) {
return (Iterator<Map<String, V>>) privToIterator(rs, type, arrayMaxLength, cal, mapValType);
}
public <T extends Map<String, V>, V> Map<String, V>[] toArrayMap(ResultSet rs, final Class<T> type, Class<V> mapValType, int arrayMaxLength, Calendar cal) {
return privToArray(rs, type, arrayMaxLength, cal, mapValType);
}
@SuppressWarnings({"unchecked"})
public <E extends Map<String, V>, V> List<Map<String, V>> toListMap(ResultSet rs, Class<E> componentType, Class<V> mapValType, int arrayMaxLength, Calendar cal) {
return (List<Map<String, V>>) privToList(rs, componentType, arrayMaxLength, cal, mapValType);
}
@SuppressWarnings({"unchecked"})
public <K, E extends Map<String, V>, V> Map<K, Map<String, V>> toMapMap(ResultSet rs, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, int arrayMaxLength, Calendar cal) {
return (Map<K, Map<String, V>>) privToMap(rs, mapKeyType, componentType, arrayMaxLength, cal, mapValType);
}
@SuppressWarnings({"unchecked"})
public <K, E extends Map<String, V>, V> Map<K, List<Map<String, V>>> toMapListMap(ResultSet rs, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, int arrayMaxLength, Calendar cal) {
return (Map<K, List<Map<String, V>>>) privToMapCollection(rs, mapKeyType, List.class, componentType, arrayMaxLength, cal, mapValType);
}
// overloaded map methods that don't require you to specify the type of map you want
@SuppressWarnings({"unchecked"})
public <V> Map<String, V> toSingleMap(ResultSet rs, Class<V> mapValType, Calendar cal) {
return toSingleMap(rs, Map.class, mapValType, cal);
}
@SuppressWarnings({"unchecked"})
public <V> ListIterator<Map<String, V>> toListIteratorMap(ResultSet rs, Class<V> mapValType, int arrayMaxLength, Calendar cal) {
return toListIteratorMap(rs, Map.class, mapValType, arrayMaxLength, cal);
}
@SuppressWarnings({"unchecked"})
public <V> Iterator<Map<String, V>> toIteratorMap(ResultSet rs, Class<V> mapValType, int arrayMaxLength, Calendar cal) {
return toIteratorMap(rs, Map.class, mapValType, arrayMaxLength, cal);
}
@SuppressWarnings({"unchecked"})
public <V> List<Map<String, V>> toListMap(ResultSet rs, Class<V> mapValType, int arrayMaxLength, Calendar cal) {
return toListMap(rs, Map.class, mapValType, arrayMaxLength, cal);
}
@SuppressWarnings({"unchecked"})
public <K, V> Map<K, Map<String, V>> toMapMap(ResultSet rs, Class<K> mapKeyType, Class<V> mapValType, int arrayMaxLength, Calendar cal) {
return toMapMap(rs, mapKeyType, Map.class, mapValType, arrayMaxLength, cal);
}
@SuppressWarnings({"unchecked"})
public <K, V> Map<K, List<Map<String, V>>> toMapListMap(ResultSet rs, Class<K> mapKeyType, Class<V> mapValType, int arrayMaxLength, Calendar cal) {
return this.toMapListMap(rs, mapKeyType, Map.class, mapValType, arrayMaxLength, cal);
}
// completely useless except inside this class
private static String getComponentName(Class<?> componentType, Class<?> mapValType){
final String componentName = componentType != null ? componentType.getName() : "UNKNOWN";
if(Map.class.isAssignableFrom(componentType))
return String.format("%s<java.lang.String, %s>",
componentName, mapValType != null ? mapValType.getName() : "java.lang.Object");
if(componentType != null && componentType.isArray())
return componentType.getComponentType().getName()+"[]";
return componentName;
}
protected void tryClose(ResultSet rs) {
//todo: if (canCloseResultSet())
TryClose.tryClose(rs);
}
// DO NOT EDIT BELOW THIS LINE, OR CHANGE THIS COMMENT, CODE AUTOMATICALLY GENERATED BY genQueryMapper.sh
public <T> T toObject(ResultSet rs, Class<T> componentType) {
return this.toObject(rs, componentType, cal);
}
public <T extends Map<String, V>, V> Map<String, V> toSingleMap(ResultSet rs, Class<T> componentType, Class<V> mapValType) {
return this.toSingleMap(rs, componentType, mapValType, cal);
}
public <V> Map<String, V> toSingleMap(ResultSet rs, Class<V> mapValType) {
return this.toSingleMap(rs, mapValType, cal);
}
public <T extends Collection<E>, E> T toCollection(ResultSet rs, final Class<T> collectionType, Class<E> componentType) {
return this.toCollection(rs, collectionType, componentType, arrayMaxLength, cal);
}
public <T extends Collection<E>, E> T toCollection(ResultSet rs, final Class<T> collectionType, Class<E> componentType, int arrayMaxLength) {
return this.toCollection(rs, collectionType, componentType, arrayMaxLength, cal);
}
public <T extends Collection<E>, E> T toCollection(ResultSet rs, final Class<T> collectionType, Class<E> componentType, Calendar cal) {
return this.toCollection(rs, collectionType, componentType, arrayMaxLength, cal);
}
public <T extends Collection<E>, E> T toCollection(ResultSet rs, T list, Class<E> componentType) {
return this.toCollection(rs, list, componentType, arrayMaxLength, cal);
}
public <T extends Collection<E>, E> T toCollection(ResultSet rs, T list, Class<E> componentType, int arrayMaxLength) {
return this.toCollection(rs, list, componentType, arrayMaxLength, cal);
}
public <T extends Collection<E>, E> T toCollection(ResultSet rs, T list, Class<E> componentType, Calendar cal) {
return this.toCollection(rs, list, componentType, arrayMaxLength, cal);
}
public <T extends Map<K, E>, K, E> T toMap(ResultSet rs, final Class<T> returnType, Class<K> mapKeyType, Class<E> componentType) {
return this.toMap(rs, returnType, mapKeyType, componentType, arrayMaxLength, cal);
}
public <T extends Map<K, E>, K, E> T toMap(ResultSet rs, final Class<T> returnType, Class<K> mapKeyType, Class<E> componentType, int arrayMaxLength) {
return this.toMap(rs, returnType, mapKeyType, componentType, arrayMaxLength, cal);
}
public <T extends Map<K, E>, K, E> T toMap(ResultSet rs, final Class<T> returnType, Class<K> mapKeyType, Class<E> componentType, Calendar cal) {
return this.toMap(rs, returnType, mapKeyType, componentType, arrayMaxLength, cal);
}
public <T extends Map<K, E>, K, E> T toMap(ResultSet rs, T map, Class<K> mapKeyType, Class<E> componentType) {
return this.toMap(rs, map, mapKeyType, componentType, arrayMaxLength, cal);
}
public <T extends Map<K, E>, K, E> T toMap(ResultSet rs, T map, Class<K> mapKeyType, Class<E> componentType, int arrayMaxLength) {
return this.toMap(rs, map, mapKeyType, componentType, arrayMaxLength, cal);
}
public <T extends Map<K, E>, K, E> T toMap(ResultSet rs, T map, Class<K> mapKeyType, Class<E> componentType, Calendar cal) {
return this.toMap(rs, map, mapKeyType, componentType, arrayMaxLength, cal);
}
public <T extends Map<K, E>, K, E extends Collection<C>, C> T toMapCollection(ResultSet rs, final Class<T> returnType, Class<K> mapKeyType, Class<E> collectionType, Class<C> componentType) {
return this.toMapCollection(rs, returnType, mapKeyType, collectionType, componentType, arrayMaxLength, cal);
}
public <T extends Map<K, E>, K, E extends Collection<C>, C> T toMapCollection(ResultSet rs, final Class<T> returnType, Class<K> mapKeyType, Class<E> collectionType, Class<C> componentType, int arrayMaxLength) {
return this.toMapCollection(rs, returnType, mapKeyType, collectionType, componentType, arrayMaxLength, cal);
}
public <T extends Map<K, E>, K, E extends Collection<C>, C> T toMapCollection(ResultSet rs, final Class<T> returnType, Class<K> mapKeyType, Class<E> collectionType, Class<C> componentType, Calendar cal) {
return this.toMapCollection(rs, returnType, mapKeyType, collectionType, componentType, arrayMaxLength, cal);
}
public <T extends Map<K, E>, K, E extends Collection<C>, C> T toMapCollection(ResultSet rs, T map, Class<K> mapKeyType, Class<E> collectionType, Class<C> componentType) {
return this.toMapCollection(rs, map, mapKeyType, collectionType, componentType, arrayMaxLength, cal);
}
public <T extends Map<K, E>, K, E extends Collection<C>, C> T toMapCollection(ResultSet rs, T map, Class<K> mapKeyType, Class<E> collectionType, Class<C> componentType, int arrayMaxLength) {
return this.toMapCollection(rs, map, mapKeyType, collectionType, componentType, arrayMaxLength, cal);
}
public <T extends Map<K, E>, K, E extends Collection<C>, C> T toMapCollection(ResultSet rs, T map, Class<K> mapKeyType, Class<E> collectionType, Class<C> componentType, Calendar cal) {
return this.toMapCollection(rs, map, mapKeyType, collectionType, componentType, arrayMaxLength, cal);
}
public <T> ListIterator<T> toListIterator(ResultSet rs, final Class<T> type) {
return this.toListIterator(rs, type, arrayMaxLength, cal);
}
public <T> ListIterator<T> toListIterator(ResultSet rs, final Class<T> type, int arrayMaxLength) {
return this.toListIterator(rs, type, arrayMaxLength, cal);
}
public <T> ListIterator<T> toListIterator(ResultSet rs, final Class<T> type, Calendar cal) {
return this.toListIterator(rs, type, arrayMaxLength, cal);
}
public <T> Iterator<T> toIterator(ResultSet rs, final Class<T> type) {
return this.toIterator(rs, type, arrayMaxLength, cal);
}
public <T> Iterator<T> toIterator(ResultSet rs, final Class<T> type, int arrayMaxLength) {
return this.toIterator(rs, type, arrayMaxLength, cal);
}
public <T> Iterator<T> toIterator(ResultSet rs, final Class<T> type, Calendar cal) {
return this.toIterator(rs, type, arrayMaxLength, cal);
}
public <T> T[] toArray(ResultSet rs, final Class<T> type) {
return this.toArray(rs, type, arrayMaxLength, cal);
}
public <T> T[] toArray(ResultSet rs, final Class<T> type, int arrayMaxLength) {
return this.toArray(rs, type, arrayMaxLength, cal);
}
public <T> T[] toArray(ResultSet rs, final Class<T> type, Calendar cal) {
return this.toArray(rs, type, arrayMaxLength, cal);
}
public <E> List<E> toList(ResultSet rs, Class<E> componentType) {
return this.toList(rs, componentType, arrayMaxLength, cal);
}
public <E> List<E> toList(ResultSet rs, Class<E> componentType, int arrayMaxLength) {
return this.toList(rs, componentType, arrayMaxLength, cal);
}
public <E> List<E> toList(ResultSet rs, Class<E> componentType, Calendar cal) {
return this.toList(rs, componentType, arrayMaxLength, cal);
}
public <K, E> Map<K, E> toMap(ResultSet rs, Class<K> mapKeyType, Class<E> componentType) {
return this.toMap(rs, mapKeyType, componentType, arrayMaxLength, cal);
}
public <K, E> Map<K, E> toMap(ResultSet rs, Class<K> mapKeyType, Class<E> componentType, int arrayMaxLength) {
return this.toMap(rs, mapKeyType, componentType, arrayMaxLength, cal);
}
public <K, E> Map<K, E> toMap(ResultSet rs, Class<K> mapKeyType, Class<E> componentType, Calendar cal) {
return this.toMap(rs, mapKeyType, componentType, arrayMaxLength, cal);
}
public <K, E extends List<C>, C> Map<K, E> toMapList(ResultSet rs, Class<K> mapKeyType, Class<C> componentType) {
return this.toMapList(rs, mapKeyType, componentType, arrayMaxLength, cal);
}
public <K, E extends List<C>, C> Map<K, E> toMapList(ResultSet rs, Class<K> mapKeyType, Class<C> componentType, int arrayMaxLength) {
return this.toMapList(rs, mapKeyType, componentType, arrayMaxLength, cal);
}
public <K, E extends List<C>, C> Map<K, E> toMapList(ResultSet rs, Class<K> mapKeyType, Class<C> componentType, Calendar cal) {
return this.toMapList(rs, mapKeyType, componentType, arrayMaxLength, cal);
}
public <T extends Collection<E>, E extends Map<String, V>, V> T toCollectionMap(ResultSet rs, final Class<T> collectionType, Class<E> componentType, Class<V> mapValType) {
return this.toCollectionMap(rs, collectionType, componentType, mapValType, arrayMaxLength, cal);
}
public <T extends Collection<E>, E extends Map<String, V>, V> T toCollectionMap(ResultSet rs, final Class<T> collectionType, Class<E> componentType, Class<V> mapValType, int arrayMaxLength) {
return this.toCollectionMap(rs, collectionType, componentType, mapValType, arrayMaxLength, cal);
}
public <T extends Collection<E>, E extends Map<String, V>, V> T toCollectionMap(ResultSet rs, final Class<T> collectionType, Class<E> componentType, Class<V> mapValType, Calendar cal) {
return this.toCollectionMap(rs, collectionType, componentType, mapValType, arrayMaxLength, cal);
}
public <T extends Collection<E>, E extends Map<String, V>, V> T toCollectionMap(ResultSet rs, T list, Class<E> componentType, Class<V> mapValType) {
return this.toCollectionMap(rs, list, componentType, mapValType, arrayMaxLength, cal);
}
public <T extends Collection<E>, E extends Map<String, V>, V> T toCollectionMap(ResultSet rs, T list, Class<E> componentType, Class<V> mapValType, int arrayMaxLength) {
return this.toCollectionMap(rs, list, componentType, mapValType, arrayMaxLength, cal);
}
public <T extends Collection<E>, E extends Map<String, V>, V> T toCollectionMap(ResultSet rs, T list, Class<E> componentType, Class<V> mapValType, Calendar cal) {
return this.toCollectionMap(rs, list, componentType, mapValType, arrayMaxLength, cal);
}
public <T extends Map<K, E>, K, E extends Map<String, V>, V> T toMapMap(ResultSet rs, final Class<T> returnType, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType) {
return this.toMapMap(rs, returnType, mapKeyType, componentType, mapValType, arrayMaxLength, cal);
}
public <T extends Map<K, E>, K, E extends Map<String, V>, V> T toMapMap(ResultSet rs, final Class<T> returnType, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, int arrayMaxLength) {
return this.toMapMap(rs, returnType, mapKeyType, componentType, mapValType, arrayMaxLength, cal);
}
public <T extends Map<K, E>, K, E extends Map<String, V>, V> T toMapMap(ResultSet rs, final Class<T> returnType, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, Calendar cal) {
return this.toMapMap(rs, returnType, mapKeyType, componentType, mapValType, arrayMaxLength, cal);
}
public <T extends Map<K, E>, K, E extends Map<String, V>, V> T toMapMap(ResultSet rs, T map, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType) {
return this.toMapMap(rs, map, mapKeyType, componentType, mapValType, arrayMaxLength, cal);
}
public <T extends Map<K, E>, K, E extends Map<String, V>, V> T toMapMap(ResultSet rs, T map, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, int arrayMaxLength) {
return this.toMapMap(rs, map, mapKeyType, componentType, mapValType, arrayMaxLength, cal);
}
public <T extends Map<K, E>, K, E extends Map<String, V>, V> T toMapMap(ResultSet rs, T map, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, Calendar cal) {
return this.toMapMap(rs, map, mapKeyType, componentType, mapValType, arrayMaxLength, cal);
}
public <T extends Map<K, C>, K, C extends Collection<E>, E extends Map<String, V>, V> T toMapCollectionMap(ResultSet rs, final Class<T> returnType, Class<K> mapKeyType, Class<C> collectionType, Class<E> componentType, Class<V> mapValType) {
return this.toMapCollectionMap(rs, returnType, mapKeyType, collectionType, componentType, mapValType, arrayMaxLength, cal);
}
public <T extends Map<K, C>, K, C extends Collection<E>, E extends Map<String, V>, V> T toMapCollectionMap(ResultSet rs, final Class<T> returnType, Class<K> mapKeyType, Class<C> collectionType, Class<E> componentType, Class<V> mapValType, int arrayMaxLength) {
return this.toMapCollectionMap(rs, returnType, mapKeyType, collectionType, componentType, mapValType, arrayMaxLength, cal);
}
public <T extends Map<K, C>, K, C extends Collection<E>, E extends Map<String, V>, V> T toMapCollectionMap(ResultSet rs, final Class<T> returnType, Class<K> mapKeyType, Class<C> collectionType, Class<E> componentType, Class<V> mapValType, Calendar cal) {
return this.toMapCollectionMap(rs, returnType, mapKeyType, collectionType, componentType, mapValType, arrayMaxLength, cal);
}
public <T extends Map<K, C>, K, C extends Collection<E>, E extends Map<String, V>, V> T toMapCollectionMap(ResultSet rs, T map, Class<K> mapKeyType, Class<C> collectionType, Class<E> componentType, Class<V> mapValType) {
return this.toMapCollectionMap(rs, map, mapKeyType, collectionType, componentType, mapValType, arrayMaxLength, cal);
}
public <T extends Map<K, C>, K, C extends Collection<E>, E extends Map<String, V>, V> T toMapCollectionMap(ResultSet rs, T map, Class<K> mapKeyType, Class<C> collectionType, Class<E> componentType, Class<V> mapValType, int arrayMaxLength) {
return this.toMapCollectionMap(rs, map, mapKeyType, collectionType, componentType, mapValType, arrayMaxLength, cal);
}
public <T extends Map<K, C>, K, C extends Collection<E>, E extends Map<String, V>, V> T toMapCollectionMap(ResultSet rs, T map, Class<K> mapKeyType, Class<C> collectionType, Class<E> componentType, Class<V> mapValType, Calendar cal) {
return this.toMapCollectionMap(rs, map, mapKeyType, collectionType, componentType, mapValType, arrayMaxLength, cal);
}
public <T extends Map<String, V>, V> ListIterator<Map<String, V>> toListIteratorMap(ResultSet rs, final Class<T> type, Class<V> mapValType) {
return this.toListIteratorMap(rs, type, mapValType, arrayMaxLength, cal);
}
public <T extends Map<String, V>, V> ListIterator<Map<String, V>> toListIteratorMap(ResultSet rs, final Class<T> type, Class<V> mapValType, int arrayMaxLength) {
return this.toListIteratorMap(rs, type, mapValType, arrayMaxLength, cal);
}
public <T extends Map<String, V>, V> ListIterator<Map<String, V>> toListIteratorMap(ResultSet rs, final Class<T> type, Class<V> mapValType, Calendar cal) {
return this.toListIteratorMap(rs, type, mapValType, arrayMaxLength, cal);
}
public <T extends Map<String, V>, V> Iterator<Map<String, V>> toIteratorMap(ResultSet rs, final Class<T> type, Class<V> mapValType) {
return this.toIteratorMap(rs, type, mapValType, arrayMaxLength, cal);
}
public <T extends Map<String, V>, V> Iterator<Map<String, V>> toIteratorMap(ResultSet rs, final Class<T> type, Class<V> mapValType, int arrayMaxLength) {
return this.toIteratorMap(rs, type, mapValType, arrayMaxLength, cal);
}
public <T extends Map<String, V>, V> Iterator<Map<String, V>> toIteratorMap(ResultSet rs, final Class<T> type, Class<V> mapValType, Calendar cal) {
return this.toIteratorMap(rs, type, mapValType, arrayMaxLength, cal);
}
public <T extends Map<String, V>, V> Map<String, V>[] toArrayMap(ResultSet rs, final Class<T> type, Class<V> mapValType) {
return this.toArrayMap(rs, type, mapValType, arrayMaxLength, cal);
}
public <T extends Map<String, V>, V> Map<String, V>[] toArrayMap(ResultSet rs, final Class<T> type, Class<V> mapValType, int arrayMaxLength) {
return this.toArrayMap(rs, type, mapValType, arrayMaxLength, cal);
}
public <T extends Map<String, V>, V> Map<String, V>[] toArrayMap(ResultSet rs, final Class<T> type, Class<V> mapValType, Calendar cal) {
return this.toArrayMap(rs, type, mapValType, arrayMaxLength, cal);
}
public <E extends Map<String, V>, V> List<Map<String, V>> toListMap(ResultSet rs, Class<E> componentType, Class<V> mapValType) {
return this.toListMap(rs, componentType, mapValType, arrayMaxLength, cal);
}
public <E extends Map<String, V>, V> List<Map<String, V>> toListMap(ResultSet rs, Class<E> componentType, Class<V> mapValType, int arrayMaxLength) {
return this.toListMap(rs, componentType, mapValType, arrayMaxLength, cal);
}
public <E extends Map<String, V>, V> List<Map<String, V>> toListMap(ResultSet rs, Class<E> componentType, Class<V> mapValType, Calendar cal) {
return this.toListMap(rs, componentType, mapValType, arrayMaxLength, cal);
}
public <K, E extends Map<String, V>, V> Map<K, Map<String, V>> toMapMap(ResultSet rs, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType) {
return this.toMapMap(rs, mapKeyType, componentType, mapValType, arrayMaxLength, cal);
}
public <K, E extends Map<String, V>, V> Map<K, Map<String, V>> toMapMap(ResultSet rs, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, int arrayMaxLength) {
return this.toMapMap(rs, mapKeyType, componentType, mapValType, arrayMaxLength, cal);
}
public <K, E extends Map<String, V>, V> Map<K, Map<String, V>> toMapMap(ResultSet rs, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, Calendar cal) {
return this.toMapMap(rs, mapKeyType, componentType, mapValType, arrayMaxLength, cal);
}
public <K, E extends Map<String, V>, V> Map<K, List<Map<String, V>>> toMapListMap(ResultSet rs, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType) {
return this.toMapListMap(rs, mapKeyType, componentType, mapValType, arrayMaxLength, cal);
}
public <K, E extends Map<String, V>, V> Map<K, List<Map<String, V>>> toMapListMap(ResultSet rs, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, int arrayMaxLength) {
return this.toMapListMap(rs, mapKeyType, componentType, mapValType, arrayMaxLength, cal);
}
public <K, E extends Map<String, V>, V> Map<K, List<Map<String, V>>> toMapListMap(ResultSet rs, Class<K> mapKeyType, Class<E> componentType, Class<V> mapValType, Calendar cal) {
return this.toMapListMap(rs, mapKeyType, componentType, mapValType, arrayMaxLength, cal);
}
public <V> ListIterator<Map<String, V>> toListIteratorMap(ResultSet rs, Class<V> mapValType) {
return this.toListIteratorMap(rs, mapValType, arrayMaxLength, cal);
}
public <V> ListIterator<Map<String, V>> toListIteratorMap(ResultSet rs, Class<V> mapValType, int arrayMaxLength) {
return this.toListIteratorMap(rs, mapValType, arrayMaxLength, cal);
}
public <V> ListIterator<Map<String, V>> toListIteratorMap(ResultSet rs, Class<V> mapValType, Calendar cal) {
return this.toListIteratorMap(rs, mapValType, arrayMaxLength, cal);
}
public <V> Iterator<Map<String, V>> toIteratorMap(ResultSet rs, Class<V> mapValType) {
return this.toIteratorMap(rs, mapValType, arrayMaxLength, cal);
}
public <V> Iterator<Map<String, V>> toIteratorMap(ResultSet rs, Class<V> mapValType, int arrayMaxLength) {
return this.toIteratorMap(rs, mapValType, arrayMaxLength, cal);
}
public <V> Iterator<Map<String, V>> toIteratorMap(ResultSet rs, Class<V> mapValType, Calendar cal) {
return this.toIteratorMap(rs, mapValType, arrayMaxLength, cal);
}
public <V> List<Map<String, V>> toListMap(ResultSet rs, Class<V> mapValType) {
return this.toListMap(rs, mapValType, arrayMaxLength, cal);
}
public <V> List<Map<String, V>> toListMap(ResultSet rs, Class<V> mapValType, int arrayMaxLength) {
return this.toListMap(rs, mapValType, arrayMaxLength, cal);
}
public <V> List<Map<String, V>> toListMap(ResultSet rs, Class<V> mapValType, Calendar cal) {
return this.toListMap(rs, mapValType, arrayMaxLength, cal);
}
public <K, V> Map<K, Map<String, V>> toMapMap(ResultSet rs, Class<K> mapKeyType, Class<V> mapValType) {
return this.toMapMap(rs, mapKeyType, mapValType, arrayMaxLength, cal);
}
public <K, V> Map<K, Map<String, V>> toMapMap(ResultSet rs, Class<K> mapKeyType, Class<V> mapValType, int arrayMaxLength) {
return this.toMapMap(rs, mapKeyType, mapValType, arrayMaxLength, cal);
}
public <K, V> Map<K, Map<String, V>> toMapMap(ResultSet rs, Class<K> mapKeyType, Class<V> mapValType, Calendar cal) {
return this.toMapMap(rs, mapKeyType, mapValType, arrayMaxLength, cal);
}
public <K, V> Map<K, List<Map<String, V>>> toMapListMap(ResultSet rs, Class<K> mapKeyType, Class<V> mapValType) {
return this.toMapListMap(rs, mapKeyType, mapValType, arrayMaxLength, cal);
}
public <K, V> Map<K, List<Map<String, V>>> toMapListMap(ResultSet rs, Class<K> mapKeyType, Class<V> mapValType, int arrayMaxLength) {
return this.toMapListMap(rs, mapKeyType, mapValType, arrayMaxLength, cal);
}
public <K, V> Map<K, List<Map<String, V>>> toMapListMap(ResultSet rs, Class<K> mapKeyType, Class<V> mapValType, Calendar cal) {
return this.toMapListMap(rs, mapKeyType, mapValType, arrayMaxLength, cal);
}
}

View File

@ -0,0 +1,240 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $Header:$
*/
package com.moparisthebest.jdbc;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Abstract base class for all row mappers.
*
* RowMappers are used to map the contents of a row in a ResultSet to the return type of an annotated method.
* Supported RowMapper types include: HashMap, Map, Object, XmlObject. When a ResultSetMapper is ready to
* map a ResultSet row to an object, it requests a RowMapper for the return type of the method from the
* RowMapperFactory.
*
*/
public abstract class RowMapper {
private static final String SETTER_NAME_REGEX = "^(set)([A-Z_]\\w*+)";
protected static final TypeMappingsFactory _tmf = TypeMappingsFactory.getInstance();
protected static final Pattern _setterRegex = Pattern.compile(SETTER_NAME_REGEX);
/** ResultSet to map. */
protected final ResultSet _resultSet;
/** Calendar instance for date/time mappings. */
protected final Calendar _cal;
/** Class to map ResultSet Rows to. */
protected final Class<?> _returnTypeClass;
/**
* 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) {
_resultSet = resultSet;
_returnTypeClass = returnTypeClass;
_cal = cal;
}
/**
* Map a ResultSet row to the return type class
* @return An instance of class.
*/
public abstract Object mapRowToReturnType();
/**
* Build a String array of column names from the ResultSet.
* @return A String array containing the column names contained within the ResultSet.
* @throws java.sql.SQLException on error
*/
protected String[] getKeysFromResultSet() throws SQLException {
String[] keys;
final ResultSetMetaData md = _resultSet.getMetaData();
final int columnCount = md.getColumnCount();
keys = new String[columnCount + 1];
for (int i = 1; i <= columnCount; i++) {
keys[i] = md.getColumnName(i).toUpperCase();
}
return keys;
}
/**
* Determine if the given method is a java bean setter method.
* @param method Method to check
* @return True if the method is a setter method.
*/
protected boolean isSetterMethod(Method method) {
Matcher matcher = _setterRegex.matcher(method.getName());
if (matcher.matches()) {
if (Modifier.isStatic(method.getModifiers())) return false;
if (!Modifier.isPublic(method.getModifiers())) return false;
if (!Void.TYPE.equals(method.getReturnType())) return false;
// method parameter checks
Class[] params = method.getParameterTypes();
if (params.length != 1) return false;
if (TypeMappingsFactory.TYPE_UNKNOWN == _tmf.getTypeId(params[0])) return false;
return true;
}
return false;
}
/**
* Extract a column value from the ResultSet and return it as resultType.
*
* @param index The column index of the value to extract from the ResultSet.
* @param resultType The return type. Defined in TypeMappingsFactory.
* @return The extracted value
* @throws java.sql.SQLException on error.
*/
protected Object extractColumnValue(int index, int resultType) throws SQLException {
switch (resultType) {
case TypeMappingsFactory.TYPE_INT:
return new Integer(_resultSet.getInt(index));
case TypeMappingsFactory.TYPE_LONG:
return new Long(_resultSet.getLong(index));
case TypeMappingsFactory.TYPE_FLOAT:
return new Float(_resultSet.getFloat(index));
case TypeMappingsFactory.TYPE_DOUBLE:
return new Double(_resultSet.getDouble(index));
case TypeMappingsFactory.TYPE_BYTE:
return new Byte(_resultSet.getByte(index));
case TypeMappingsFactory.TYPE_SHORT:
return new Short(_resultSet.getShort(index));
case TypeMappingsFactory.TYPE_BOOLEAN:
return _resultSet.getBoolean(index) ? Boolean.TRUE : Boolean.FALSE;
case TypeMappingsFactory.TYPE_INT_OBJ:
{
int i = _resultSet.getInt(index);
return _resultSet.wasNull() ? null : new Integer(i);
}
case TypeMappingsFactory.TYPE_LONG_OBJ:
{
long i = _resultSet.getLong(index);
return _resultSet.wasNull() ? null : new Long(i);
}
case TypeMappingsFactory.TYPE_FLOAT_OBJ:
{
float i = _resultSet.getFloat(index);
return _resultSet.wasNull() ? null : new Float(i);
}
case TypeMappingsFactory.TYPE_DOUBLE_OBJ:
{
double i = _resultSet.getDouble(index);
return _resultSet.wasNull() ? null : new Double(i);
}
case TypeMappingsFactory.TYPE_BYTE_OBJ:
{
byte i = _resultSet.getByte(index);
return _resultSet.wasNull() ? null : new Byte(i);
}
case TypeMappingsFactory.TYPE_SHORT_OBJ:
{
short i = _resultSet.getShort(index);
return _resultSet.wasNull() ? null : new Short(i);
}
case TypeMappingsFactory.TYPE_BOOLEAN_OBJ:
{
boolean i = _resultSet.getBoolean(index);
return _resultSet.wasNull() ? null : (i ? Boolean.TRUE : Boolean.FALSE);
}
case TypeMappingsFactory.TYPE_STRING:
case TypeMappingsFactory.TYPE_XMLBEAN_ENUM:
return _resultSet.getString(index);
case TypeMappingsFactory.TYPE_BIG_DECIMAL:
return _resultSet.getBigDecimal(index);
case TypeMappingsFactory.TYPE_BYTES:
return _resultSet.getBytes(index);
case TypeMappingsFactory.TYPE_TIMESTAMP:
{
if (null == _cal)
return _resultSet.getTimestamp(index);
else
return _resultSet.getTimestamp(index, _cal);
}
case TypeMappingsFactory.TYPE_TIME:
{
if (null == _cal)
return _resultSet.getTime(index);
else
return _resultSet.getTime(index, _cal);
}
case TypeMappingsFactory.TYPE_SQLDATE:
{
if (null == _cal)
return _resultSet.getDate(index);
else
return _resultSet.getDate(index, _cal);
}
case TypeMappingsFactory.TYPE_DATE:
{
// convert explicity to java.util.Date
// 12918 | knex does not return java.sql.Date properly from web service
java.sql.Timestamp ts = (null == _cal) ? _resultSet.getTimestamp(index) : _resultSet.getTimestamp(index, _cal);
if (null == ts)
return null;
return new java.util.Date(ts.getTime());
}
case TypeMappingsFactory.TYPE_CALENDAR:
{
java.sql.Timestamp ts = (null == _cal) ? _resultSet.getTimestamp(index) : _resultSet.getTimestamp(index, _cal);
if (null == ts)
return null;
Calendar c = (null == _cal) ? Calendar.getInstance() : (Calendar) _cal.clone();
c.setTimeInMillis(ts.getTime());
return c;
}
case TypeMappingsFactory.TYPE_REF:
return _resultSet.getRef(index);
case TypeMappingsFactory.TYPE_BLOB:
return _resultSet.getBlob(index);
case TypeMappingsFactory.TYPE_CLOB:
return _resultSet.getClob(index);
case TypeMappingsFactory.TYPE_ARRAY:
return _resultSet.getArray(index);
case TypeMappingsFactory.TYPE_READER:
case TypeMappingsFactory.TYPE_STREAM:
throw new MapperException("streaming return types are not supported by the JdbcControl; use ResultSet instead");
case TypeMappingsFactory.TYPE_STRUCT:
case TypeMappingsFactory.TYPE_UNKNOWN:
// JAVA_TYPE (could be any), or REF
return _resultSet.getObject(index);
default:
throw new MapperException("internal error: unknown type ID: " + Integer.toString(resultType));
}
}
}

View File

@ -0,0 +1,426 @@
package com.moparisthebest.jdbc;
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $Header:$
*/
import java.lang.reflect.*;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import static com.moparisthebest.jdbc.UpdateableDTO.YES;
import static com.moparisthebest.jdbc.UpdateableDTO.NO;
/**
* Map a ResultSet row to an Object. This mapper uses Java reflection to perform the mapping.
* <p/>
* This class is modified from org.apache.beehive.controls.system.jdbc.RowToObjectMapper
* <p/>
* The column names are compared, case insensitive, and with and without underscores (_), to the set* methods
* and fields of the given class to map the fields. For example:
* <p/>
* USERID would prefer method setUserId(), and fall back to field userId if the method doesn't exist
* USER_ID would act the same as the above, but also additionally try to match method setUser_Id(), or field user_id
* <p/>
* First, this class will look for a constructor that takes a ResultSet as a parameter, if it finds one, it will
* instantiate it with that constructor, sending in the ResultSet. Otherwise, this will only try to use public
* setters, but will set fields regardless of specified access, even private fields.
*
* @author Travis Burtrum (modifications from beehive)
*/
public class RowToObjectMapper<T> extends RowMapper {
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?
protected final int _columnCount;
protected final Constructor<T> resultSetConstructor;
protected final Class<? extends T> _returnTypeClass; // over-ride non-generic version of this in super class
// only non-null when _returnTypeClass is an array, or a map
protected final Class<?> componentType;
protected final boolean returnMap;
protected AccessibleObject[] _fields;
protected int[] _fieldTypes;
protected final Object[] _args = new Object[1];
public RowToObjectMapper(ResultSet resultSet, Class<T> returnTypeClass) {
this(resultSet, returnTypeClass, null, null);
}
public RowToObjectMapper(ResultSet resultSet, Class<T> returnTypeClass, Class<?> mapValType) {
this(resultSet, returnTypeClass, null, mapValType);
}
public RowToObjectMapper(ResultSet resultSet, Class<T> returnTypeClass, Calendar cal) {
this(resultSet, returnTypeClass, cal, null);
}
/**
* Create a new RowToObjectMapper.
*
* @param resultSet ResultSet to map
* @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);
returnMap = Map.class.isAssignableFrom(returnTypeClass);
if(returnMap){
_returnTypeClass = ResultSetMapper.getConcreteClass(returnTypeClass, HashMap.class);
componentType = mapValType;
}else{
_returnTypeClass = returnTypeClass;
// detect if we want an array back
componentType = returnTypeClass.getComponentType();
}
_fields = null;
// detect if returnTypeClass has a constructor that takes a ResultSet, if so, our job couldn't be easier...
Constructor<T> resultSetConstructor = null;
try {
resultSetConstructor = returnTypeClass.getConstructor(ResultSet.class);
if (!resultSetConstructor.isAccessible())
resultSetConstructor.setAccessible(true);
} catch (Throwable e) {
// do nothing, no such constructor
}
this.resultSetConstructor = resultSetConstructor;
try {
_columnCount = resultSet.getMetaData().getColumnCount();
} catch (SQLException e) {
throw new MapperException("RowToObjectMapper: SQLException: " + e.getMessage(), e);
}
}
/**
* Do the mapping.
*
* @return An object instance.
*/
@SuppressWarnings({"unchecked"})
public T mapRowToReturnType() {
if (resultSetConstructor != null)
try {
return resultSetConstructor.newInstance(_resultSet);
} catch (Throwable e) {
throw new MapperException(e.getClass().getName() + " when trying to create instance of : "
+ _returnTypeClass.getName() + " sending in a ResultSet object as a parameter", e);
}
if(returnMap) // we want a map
try {
final Map<String, Object> ret = (Map<String, Object>)_returnTypeClass.newInstance();
final ResultSetMetaData md = _resultSet.getMetaData();
final int columnLength = _columnCount+1;
if(componentType != null && componentType != Object.class){ // we want a specific value type
int typeId = _tmf.getTypeId(componentType);
for(int x = 1; x < columnLength; ++x)
ret.put(md.getColumnName(x).toLowerCase(), extractColumnValue(x, typeId));
} else // we want a generic object type
for(int x = 1; x < columnLength; ++x)
ret.put(md.getColumnName(x).toLowerCase(), _resultSet.getObject(x));
return _returnTypeClass.cast(ret);
} catch (Throwable e) {
throw new MapperException(e.getClass().getName() + " when trying to create a Map<String, "
+ (componentType == null ? "java.lang.Object" : componentType.getName()) + "> from a ResultSet row" +
", all columns must be of the map value type", e);
}
else if(componentType != null) // we want an array
try {
final Object[] ret = (Object[])Array.newInstance(componentType, _columnCount);
final int typeId = _tmf.getTypeId(componentType);
for(int x = 0; x < _columnCount;)
ret[x] = extractColumnValue(++x, typeId);
return _returnTypeClass.cast(ret);
} catch (Throwable e) {
throw new MapperException(e.getClass().getName() + " when trying to create a "
+ componentType.getName() + "[] from a ResultSet row, all columns must be of that type", e);
}
T resultObject = null;
// if the ResultSet only contains a single column we may be able to map directly
// to the return type -- if so we don't need to build any structures to support
// mapping
if (_columnCount == 1) {
final int typeId = _tmf.getTypeId(_returnTypeClass);
try {
if (typeId != TypeMappingsFactory.TYPE_UNKNOWN) {
return _returnTypeClass.cast(extractColumnValue(1, typeId));
} else {
// we still might want a single value (i.e. java.util.Date)
Object val = extractColumnValue(1, typeId);
if (_returnTypeClass.isAssignableFrom(val.getClass())) {
return _returnTypeClass.cast(val);
}
}
} catch (Exception e) {
throw new MapperException(e.getMessage(), e);
}
}
if (_fields == null) {
try {
getFieldMappings();
} catch (SQLException e) {
throw new MapperException(e.getMessage(), e);
}
}
try {
resultObject = _returnTypeClass.newInstance();
} catch (Throwable e) {
throw new MapperException(e.getClass().getName() + " when trying to create instance of : "
+ _returnTypeClass.getName(), e);
}
for (int i = 1; i < _fields.length; i++) {
AccessibleObject f = _fields[i];
try {
_args[0] = extractColumnValue(i, _fieldTypes[i]);
//System.out.printf("field: '%s' obj: '%s' fieldType: '%s'\n", _fields[i], _args[0], _fieldTypes[i]);
// custom hacked-in support for enums, can do better when we scrap org.apache.beehive.controls.system.jdbc.TypeMappingsFactory
if(_fieldTypes[i] == 0 && _args[0] instanceof String){
Class<?> fieldType = f instanceof Field ? ((Field)f).getType() : ((Method)f).getParameterTypes()[0];
if(Enum.class.isAssignableFrom(fieldType))
_args[0] = Enum.valueOf((Class<? extends Enum>)fieldType, (String)_args[0]);
}
if (f instanceof Field) {
((Field) f).set(resultObject, _args[0]);
} else {
((Method) f).invoke(resultObject, _args);
}
} catch (SQLException e) {
throw new MapperException(e.getMessage(), e);
} catch (IllegalArgumentException iae) {
try {
ResultSetMetaData md = _resultSet.getMetaData();
if (f instanceof Field) {
throw new MapperException("The declared Java type for field " + ((Field) f).getName()
+ ((Field) f).getType().toString()
+ " is incompatible with the SQL format of column " + i + " '" + md.getColumnName(i)
+ "' (" + md.getColumnTypeName(i)
+ ") which returns objects of type " + _args[0].getClass().getName());
} else {
throw new MapperException("The declared Java type for method " + ((Method) f).getName()
+ ((Method) f).getParameterTypes()[0].toString()
+ " is incompatible with the SQL format of column " + i + " '" + md.getColumnName(i)
+ "' (" + md.getColumnTypeName(i)
+ ") which returns objects of type " + _args[0].getClass().getName());
}
} catch (SQLException e) {
throw new MapperException(e.getMessage(), e);
}
} catch (IllegalAccessException e) {
if (f instanceof Field) {
throw new MapperException("IllegalAccessException when trying to access field " + ((Field) f).getName(), e);
} else {
throw new MapperException("IllegalAccessException when trying to access method " + ((Method) f).getName(), e);
}
} catch (InvocationTargetException e) {
throw new MapperException("InvocationTargetException when trying to access method " + ((Method) f).getName(), e);
}
}
// if this resultObject is Finishable, call finish()
if (resultObject instanceof Finishable)
try {
((Finishable) resultObject).finish(_resultSet);
} catch (SQLException e) {
throw new MapperException(e.getMessage(), e);
}
return resultObject;
}
/**
* Provided so we can extract a column value to use for the key of a map
*
* @param index
* @param classType
* @return
* @throws SQLException
*/
@SuppressWarnings({"unchecked"})
public <E> E extractColumnValue(int index, Class<E> classType) throws SQLException {
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
*
* @throws SQLException on error.
*/
protected void getFieldMappings()
throws SQLException {
final String[] keys = getKeysFromResultSet();
//System.out.println("keys: "+ Arrays.toString(keys));
// added this to handle stripping '_' from keys
Map<String, String> strippedKeys = new HashMap<String, String>();
for (final String key : keys) {
String strippedKey = key;
if (key != null) {
strippedKey = key.replaceAll("_", "");
if (key.equals(strippedKey))
continue;
strippedKeys.put(strippedKey, key);
}
}
//System.out.println("strippedKeys: "+strippedKeys);
//
// find fields or setters for return class
//
HashMap<String, AccessibleObject> mapFields = new HashMap<String, AccessibleObject>(_columnCount * 2);
for (int i = 1; i <= _columnCount; i++) {
mapFields.put(keys[i], null);
}
// public methods
Method[] classMethods = _returnTypeClass.getMethods();
for (Method m : classMethods) {
//System.out.printf("method: '%s', isSetterMethod: '%s'\n", m, isSetterMethod(m));
if (isSetterMethod(m)) {
String fieldName = m.getName().substring(3).toUpperCase();
//System.out.println("METHOD-fieldName: "+fieldName);
if (!mapFields.containsKey(fieldName)) {
fieldName = strippedKeys.get(fieldName);
if (fieldName == null)
continue;
}
// check for overloads
Object field = mapFields.get(fieldName);
if (field == null) {
mapFields.put(fieldName, m);
} else {
throw new MapperException("Unable to choose between overloaded methods " + m.getName()
+ " on the " + _returnTypeClass.getName() + " class. Mapping is done using "
+ "a case insensitive comparison of SQL ResultSet columns to field "
+ "names and public setter methods on the return class. Columns are also "
+ "stripped of '_' and compared if no match is found with them.");
}
}
}
// fix for 8813: include inherited and non-public fields
for (Class clazz = _returnTypeClass; clazz != null && clazz != Object.class; clazz = clazz.getSuperclass()) {
//System.out.println("searching for fields in class: "+clazz.getName());
Field[] classFields = clazz.getDeclaredFields();
//System.out.println("fields in class: "+Arrays.toString(classFields));
for (Field f : classFields) {
if (Modifier.isStatic(f.getModifiers())) continue;
//if (!Modifier.isPublic(f.getModifiers())) continue; // commented this out to work on all types of fields
String fieldName = f.getName().toUpperCase();
//System.out.println("fieldName: "+fieldName);
if (!mapFields.containsKey(fieldName)) {
fieldName = strippedKeys.get(fieldName);
if (fieldName == null)
continue;
}
Object field = mapFields.get(fieldName);
if (field == null) {
mapFields.put(fieldName, f);
}
}
}
// finally actually init the fields array
_fields = new AccessibleObject[_columnCount + 1];
_fieldTypes = new int[_columnCount + 1];
for (int i = 1; i < _fields.length; i++) {
AccessibleObject f = mapFields.get(keys[i]);
if (f == null) {
throw new MapperException("Unable to map the SQL column " + keys[i]
+ " to a field on the " + _returnTypeClass.getName() +
" class. Mapping is done using a case insensitive comparision of SQL ResultSet "
+ "columns to field "
+ "names and public setter methods on the return class. Columns are also "
+ "stripped of '_' and compared if no match is found with them.");
}
f.setAccessible(true);
_fields[i] = f;
if (f instanceof Field) {
_fieldTypes[i] = _tmf.getTypeId(((Field) f).getType());
} else {
_fieldTypes[i] = _tmf.getTypeId(((Method) f).getParameterTypes()[0]);
}
}
}
@Override
protected Object extractColumnValue(int index, int resultType) throws SQLException {
try{
if (resultType != TYPE_BOOLEAN && resultType != TYPE_BOOLEAN_OBJ)
return super.extractColumnValue(index, resultType);
else {
// do some special handling to convert a database string to a boolean
boolean ret;
try {
// try to get an actual boolean from the database
ret = _resultSet.getBoolean(index);
// null seems to get returned as false above, so String code won't run if its null
if (_resultSet.wasNull())
if (resultType == TYPE_BOOLEAN_OBJ)
return null; // only return null for Boolean object
else
throw new MapperException(String.format("Implicit conversion of database string to boolean failed on column '%d'. Returned string needs to be 'Y' or 'N' and was instead 'null'. If you want to accept null values, make it an object Boolean instead of primitive boolean.", index));
} catch (SQLException e) {
// if we are here, it wasn't a boolean or null, so try to grab a string instead
String bool = _resultSet.getString(index);//.toUpperCase(); // do we want it case-insensitive?
ret = YES.equals(bool);
if (!ret && !NO.equals(bool))
throw new MapperException(String.format("Implicit conversion of database string to boolean failed on column '%d'. Returned string needs to be 'Y' or 'N' and was instead '%s'.", index, bool));
//throw e;
}
return ret ? Boolean.TRUE : Boolean.FALSE;
}
}catch(SQLException e){
throw new SQLExceptionColumnNum(e, index);
}
}
public static <T> T fixNull(Class<T> returnType) {
return returnType.cast(_tmf.fixNull(returnType));
}
}

View File

@ -0,0 +1,17 @@
package com.moparisthebest.jdbc;
import java.sql.SQLException;
public class SQLExceptionColumnNum extends SQLException {
private final int columnNum;
public SQLExceptionColumnNum(Throwable cause, int columnNum) {
super("At column number "+columnNum, cause);
this.columnNum = columnNum;
}
public int getColumnNum() {
return columnNum;
}
}

View File

@ -0,0 +1,989 @@
package com.moparisthebest.jdbc;
import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.*;
import java.util.Calendar;
import java.util.Map;
/**
* This does exactly what you would expect, delegate to a ResultSet and close a Statement object when you close this ResultSet
*/
@SuppressWarnings("deprecation")
public class StatementClosingResultSet implements ResultSet {
private final ResultSet delegate;
private final Statement statement;
public StatementClosingResultSet(ResultSet delegate, Statement statement) {
this.delegate = delegate;
this.statement = statement;
}
/**
* This is the only method here that doesn't ONLY delegate
*
* @throws SQLException
*/
@Override
public void close() throws SQLException {
delegate.close();
if (statement != null)
statement.close();
}
@Override
public boolean next() throws SQLException {
return delegate.next();
}
@Override
public boolean wasNull() throws SQLException {
return delegate.wasNull();
}
@Override
public String getString(int columnIndex) throws SQLException {
return delegate.getString(columnIndex);
}
@Override
public boolean getBoolean(int columnIndex) throws SQLException {
return delegate.getBoolean(columnIndex);
}
@Override
public byte getByte(int columnIndex) throws SQLException {
return delegate.getByte(columnIndex);
}
@Override
public short getShort(int columnIndex) throws SQLException {
return delegate.getShort(columnIndex);
}
@Override
public int getInt(int columnIndex) throws SQLException {
return delegate.getInt(columnIndex);
}
@Override
public long getLong(int columnIndex) throws SQLException {
return delegate.getLong(columnIndex);
}
@Override
public float getFloat(int columnIndex) throws SQLException {
return delegate.getFloat(columnIndex);
}
@Override
public double getDouble(int columnIndex) throws SQLException {
return delegate.getDouble(columnIndex);
}
@Override
public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
return delegate.getBigDecimal(columnIndex, scale);
}
@Override
public byte[] getBytes(int columnIndex) throws SQLException {
return delegate.getBytes(columnIndex);
}
@Override
public Date getDate(int columnIndex) throws SQLException {
return delegate.getDate(columnIndex);
}
@Override
public Time getTime(int columnIndex) throws SQLException {
return delegate.getTime(columnIndex);
}
@Override
public Timestamp getTimestamp(int columnIndex) throws SQLException {
return delegate.getTimestamp(columnIndex);
}
@Override
public InputStream getAsciiStream(int columnIndex) throws SQLException {
return delegate.getAsciiStream(columnIndex);
}
@Override
public InputStream getUnicodeStream(int columnIndex) throws SQLException {
return delegate.getUnicodeStream(columnIndex);
}
@Override
public InputStream getBinaryStream(int columnIndex) throws SQLException {
return delegate.getBinaryStream(columnIndex);
}
@Override
public String getString(String columnLabel) throws SQLException {
return delegate.getString(columnLabel);
}
@Override
public boolean getBoolean(String columnLabel) throws SQLException {
return delegate.getBoolean(columnLabel);
}
@Override
public byte getByte(String columnLabel) throws SQLException {
return delegate.getByte(columnLabel);
}
@Override
public short getShort(String columnLabel) throws SQLException {
return delegate.getShort(columnLabel);
}
@Override
public int getInt(String columnLabel) throws SQLException {
return delegate.getInt(columnLabel);
}
@Override
public long getLong(String columnLabel) throws SQLException {
return delegate.getLong(columnLabel);
}
@Override
public float getFloat(String columnLabel) throws SQLException {
return delegate.getFloat(columnLabel);
}
@Override
public double getDouble(String columnLabel) throws SQLException {
return delegate.getDouble(columnLabel);
}
@Override
public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException {
return delegate.getBigDecimal(columnLabel, scale);
}
@Override
public byte[] getBytes(String columnLabel) throws SQLException {
return delegate.getBytes(columnLabel);
}
@Override
public Date getDate(String columnLabel) throws SQLException {
return delegate.getDate(columnLabel);
}
@Override
public Time getTime(String columnLabel) throws SQLException {
return delegate.getTime(columnLabel);
}
@Override
public Timestamp getTimestamp(String columnLabel) throws SQLException {
return delegate.getTimestamp(columnLabel);
}
@Override
public InputStream getAsciiStream(String columnLabel) throws SQLException {
return delegate.getAsciiStream(columnLabel);
}
@Override
public InputStream getUnicodeStream(String columnLabel) throws SQLException {
return delegate.getUnicodeStream(columnLabel);
}
@Override
public InputStream getBinaryStream(String columnLabel) throws SQLException {
return delegate.getBinaryStream(columnLabel);
}
@Override
public SQLWarning getWarnings() throws SQLException {
return delegate.getWarnings();
}
@Override
public void clearWarnings() throws SQLException {
delegate.clearWarnings();
}
@Override
public String getCursorName() throws SQLException {
return delegate.getCursorName();
}
@Override
public ResultSetMetaData getMetaData() throws SQLException {
return delegate.getMetaData();
}
@Override
public Object getObject(int columnIndex) throws SQLException {
return delegate.getObject(columnIndex);
}
@Override
public Object getObject(String columnLabel) throws SQLException {
return delegate.getObject(columnLabel);
}
@Override
public int findColumn(String columnLabel) throws SQLException {
return delegate.findColumn(columnLabel);
}
@Override
public Reader getCharacterStream(int columnIndex) throws SQLException {
return delegate.getCharacterStream(columnIndex);
}
@Override
public Reader getCharacterStream(String columnLabel) throws SQLException {
return delegate.getCharacterStream(columnLabel);
}
@Override
public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
return delegate.getBigDecimal(columnIndex);
}
@Override
public BigDecimal getBigDecimal(String columnLabel) throws SQLException {
return delegate.getBigDecimal(columnLabel);
}
@Override
public boolean isBeforeFirst() throws SQLException {
return delegate.isBeforeFirst();
}
@Override
public boolean isAfterLast() throws SQLException {
return delegate.isAfterLast();
}
@Override
public boolean isFirst() throws SQLException {
return delegate.isFirst();
}
@Override
public boolean isLast() throws SQLException {
return delegate.isLast();
}
@Override
public void beforeFirst() throws SQLException {
delegate.beforeFirst();
}
@Override
public void afterLast() throws SQLException {
delegate.afterLast();
}
@Override
public boolean first() throws SQLException {
return delegate.first();
}
@Override
public boolean last() throws SQLException {
return delegate.last();
}
@Override
public int getRow() throws SQLException {
return delegate.getRow();
}
@Override
public boolean absolute(int row) throws SQLException {
return delegate.absolute(row);
}
@Override
public boolean relative(int rows) throws SQLException {
return delegate.relative(rows);
}
@Override
public boolean previous() throws SQLException {
return delegate.previous();
}
@Override
public void setFetchDirection(int direction) throws SQLException {
delegate.setFetchDirection(direction);
}
@Override
public int getFetchDirection() throws SQLException {
return delegate.getFetchDirection();
}
@Override
public void setFetchSize(int rows) throws SQLException {
delegate.setFetchSize(rows);
}
@Override
public int getFetchSize() throws SQLException {
return delegate.getFetchSize();
}
@Override
public int getType() throws SQLException {
return delegate.getType();
}
@Override
public int getConcurrency() throws SQLException {
return delegate.getConcurrency();
}
@Override
public boolean rowUpdated() throws SQLException {
return delegate.rowUpdated();
}
@Override
public boolean rowInserted() throws SQLException {
return delegate.rowInserted();
}
@Override
public boolean rowDeleted() throws SQLException {
return delegate.rowDeleted();
}
@Override
public void updateNull(int columnIndex) throws SQLException {
delegate.updateNull(columnIndex);
}
@Override
public void updateBoolean(int columnIndex, boolean x) throws SQLException {
delegate.updateBoolean(columnIndex, x);
}
@Override
public void updateByte(int columnIndex, byte x) throws SQLException {
delegate.updateByte(columnIndex, x);
}
@Override
public void updateShort(int columnIndex, short x) throws SQLException {
delegate.updateShort(columnIndex, x);
}
@Override
public void updateInt(int columnIndex, int x) throws SQLException {
delegate.updateInt(columnIndex, x);
}
@Override
public void updateLong(int columnIndex, long x) throws SQLException {
delegate.updateLong(columnIndex, x);
}
@Override
public void updateFloat(int columnIndex, float x) throws SQLException {
delegate.updateFloat(columnIndex, x);
}
@Override
public void updateDouble(int columnIndex, double x) throws SQLException {
delegate.updateDouble(columnIndex, x);
}
@Override
public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {
delegate.updateBigDecimal(columnIndex, x);
}
@Override
public void updateString(int columnIndex, String x) throws SQLException {
delegate.updateString(columnIndex, x);
}
@Override
public void updateBytes(int columnIndex, byte[] x) throws SQLException {
delegate.updateBytes(columnIndex, x);
}
@Override
public void updateDate(int columnIndex, Date x) throws SQLException {
delegate.updateDate(columnIndex, x);
}
@Override
public void updateTime(int columnIndex, Time x) throws SQLException {
delegate.updateTime(columnIndex, x);
}
@Override
public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException {
delegate.updateTimestamp(columnIndex, x);
}
@Override
public void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException {
delegate.updateAsciiStream(columnIndex, x, length);
}
@Override
public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException {
delegate.updateBinaryStream(columnIndex, x, length);
}
@Override
public void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException {
delegate.updateCharacterStream(columnIndex, x, length);
}
@Override
public void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQLException {
delegate.updateObject(columnIndex, x, scaleOrLength);
}
@Override
public void updateObject(int columnIndex, Object x) throws SQLException {
delegate.updateObject(columnIndex, x);
}
@Override
public void updateNull(String columnLabel) throws SQLException {
delegate.updateNull(columnLabel);
}
@Override
public void updateBoolean(String columnLabel, boolean x) throws SQLException {
delegate.updateBoolean(columnLabel, x);
}
@Override
public void updateByte(String columnLabel, byte x) throws SQLException {
delegate.updateByte(columnLabel, x);
}
@Override
public void updateShort(String columnLabel, short x) throws SQLException {
delegate.updateShort(columnLabel, x);
}
@Override
public void updateInt(String columnLabel, int x) throws SQLException {
delegate.updateInt(columnLabel, x);
}
@Override
public void updateLong(String columnLabel, long x) throws SQLException {
delegate.updateLong(columnLabel, x);
}
@Override
public void updateFloat(String columnLabel, float x) throws SQLException {
delegate.updateFloat(columnLabel, x);
}
@Override
public void updateDouble(String columnLabel, double x) throws SQLException {
delegate.updateDouble(columnLabel, x);
}
@Override
public void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException {
delegate.updateBigDecimal(columnLabel, x);
}
@Override
public void updateString(String columnLabel, String x) throws SQLException {
delegate.updateString(columnLabel, x);
}
@Override
public void updateBytes(String columnLabel, byte[] x) throws SQLException {
delegate.updateBytes(columnLabel, x);
}
@Override
public void updateDate(String columnLabel, Date x) throws SQLException {
delegate.updateDate(columnLabel, x);
}
@Override
public void updateTime(String columnLabel, Time x) throws SQLException {
delegate.updateTime(columnLabel, x);
}
@Override
public void updateTimestamp(String columnLabel, Timestamp x) throws SQLException {
delegate.updateTimestamp(columnLabel, x);
}
@Override
public void updateAsciiStream(String columnLabel, InputStream x, int length) throws SQLException {
delegate.updateAsciiStream(columnLabel, x, length);
}
@Override
public void updateBinaryStream(String columnLabel, InputStream x, int length) throws SQLException {
delegate.updateBinaryStream(columnLabel, x, length);
}
@Override
public void updateCharacterStream(String columnLabel, Reader reader, int length) throws SQLException {
delegate.updateCharacterStream(columnLabel, reader, length);
}
@Override
public void updateObject(String columnLabel, Object x, int scaleOrLength) throws SQLException {
delegate.updateObject(columnLabel, x, scaleOrLength);
}
@Override
public void updateObject(String columnLabel, Object x) throws SQLException {
delegate.updateObject(columnLabel, x);
}
@Override
public void insertRow() throws SQLException {
delegate.insertRow();
}
@Override
public void updateRow() throws SQLException {
delegate.updateRow();
}
@Override
public void deleteRow() throws SQLException {
delegate.deleteRow();
}
@Override
public void refreshRow() throws SQLException {
delegate.refreshRow();
}
@Override
public void cancelRowUpdates() throws SQLException {
delegate.cancelRowUpdates();
}
@Override
public void moveToInsertRow() throws SQLException {
delegate.moveToInsertRow();
}
@Override
public void moveToCurrentRow() throws SQLException {
delegate.moveToCurrentRow();
}
@Override
public Statement getStatement() throws SQLException {
return delegate.getStatement();
}
@Override
public Object getObject(int columnIndex, Map<String, Class<?>> map) throws SQLException {
return delegate.getObject(columnIndex, map);
}
@Override
public Ref getRef(int columnIndex) throws SQLException {
return delegate.getRef(columnIndex);
}
@Override
public Blob getBlob(int columnIndex) throws SQLException {
return delegate.getBlob(columnIndex);
}
@Override
public Clob getClob(int columnIndex) throws SQLException {
return delegate.getClob(columnIndex);
}
@Override
public Array getArray(int columnIndex) throws SQLException {
return delegate.getArray(columnIndex);
}
@Override
public Object getObject(String columnLabel, Map<String, Class<?>> map) throws SQLException {
return delegate.getObject(columnLabel, map);
}
@Override
public Ref getRef(String columnLabel) throws SQLException {
return delegate.getRef(columnLabel);
}
@Override
public Blob getBlob(String columnLabel) throws SQLException {
return delegate.getBlob(columnLabel);
}
@Override
public Clob getClob(String columnLabel) throws SQLException {
return delegate.getClob(columnLabel);
}
@Override
public Array getArray(String columnLabel) throws SQLException {
return delegate.getArray(columnLabel);
}
@Override
public Date getDate(int columnIndex, Calendar cal) throws SQLException {
return delegate.getDate(columnIndex, cal);
}
@Override
public Date getDate(String columnLabel, Calendar cal) throws SQLException {
return delegate.getDate(columnLabel, cal);
}
@Override
public Time getTime(int columnIndex, Calendar cal) throws SQLException {
return delegate.getTime(columnIndex, cal);
}
@Override
public Time getTime(String columnLabel, Calendar cal) throws SQLException {
return delegate.getTime(columnLabel, cal);
}
@Override
public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {
return delegate.getTimestamp(columnIndex, cal);
}
@Override
public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException {
return delegate.getTimestamp(columnLabel, cal);
}
@Override
public URL getURL(int columnIndex) throws SQLException {
return delegate.getURL(columnIndex);
}
@Override
public URL getURL(String columnLabel) throws SQLException {
return delegate.getURL(columnLabel);
}
@Override
public void updateRef(int columnIndex, Ref x) throws SQLException {
delegate.updateRef(columnIndex, x);
}
@Override
public void updateRef(String columnLabel, Ref x) throws SQLException {
delegate.updateRef(columnLabel, x);
}
@Override
public void updateBlob(int columnIndex, Blob x) throws SQLException {
delegate.updateBlob(columnIndex, x);
}
@Override
public void updateBlob(String columnLabel, Blob x) throws SQLException {
delegate.updateBlob(columnLabel, x);
}
@Override
public void updateClob(int columnIndex, Clob x) throws SQLException {
delegate.updateClob(columnIndex, x);
}
@Override
public void updateClob(String columnLabel, Clob x) throws SQLException {
delegate.updateClob(columnLabel, x);
}
@Override
public void updateArray(int columnIndex, Array x) throws SQLException {
delegate.updateArray(columnIndex, x);
}
@Override
public void updateArray(String columnLabel, Array x) throws SQLException {
delegate.updateArray(columnLabel, x);
}
@Override
public RowId getRowId(int columnIndex) throws SQLException {
return delegate.getRowId(columnIndex);
}
@Override
public RowId getRowId(String columnLabel) throws SQLException {
return delegate.getRowId(columnLabel);
}
@Override
public void updateRowId(int columnIndex, RowId x) throws SQLException {
delegate.updateRowId(columnIndex, x);
}
@Override
public void updateRowId(String columnLabel, RowId x) throws SQLException {
delegate.updateRowId(columnLabel, x);
}
@Override
public int getHoldability() throws SQLException {
return delegate.getHoldability();
}
@Override
public boolean isClosed() throws SQLException {
return delegate.isClosed();
}
@Override
public void updateNString(int columnIndex, String nString) throws SQLException {
delegate.updateNString(columnIndex, nString);
}
@Override
public void updateNString(String columnLabel, String nString) throws SQLException {
delegate.updateNString(columnLabel, nString);
}
@Override
public void updateNClob(int columnIndex, NClob nClob) throws SQLException {
delegate.updateNClob(columnIndex, nClob);
}
@Override
public void updateNClob(String columnLabel, NClob nClob) throws SQLException {
delegate.updateNClob(columnLabel, nClob);
}
@Override
public NClob getNClob(int columnIndex) throws SQLException {
return delegate.getNClob(columnIndex);
}
@Override
public NClob getNClob(String columnLabel) throws SQLException {
return delegate.getNClob(columnLabel);
}
@Override
public SQLXML getSQLXML(int columnIndex) throws SQLException {
return delegate.getSQLXML(columnIndex);
}
@Override
public SQLXML getSQLXML(String columnLabel) throws SQLException {
return delegate.getSQLXML(columnLabel);
}
@Override
public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException {
delegate.updateSQLXML(columnIndex, xmlObject);
}
@Override
public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException {
delegate.updateSQLXML(columnLabel, xmlObject);
}
@Override
public String getNString(int columnIndex) throws SQLException {
return delegate.getNString(columnIndex);
}
@Override
public String getNString(String columnLabel) throws SQLException {
return delegate.getNString(columnLabel);
}
@Override
public Reader getNCharacterStream(int columnIndex) throws SQLException {
return delegate.getNCharacterStream(columnIndex);
}
@Override
public Reader getNCharacterStream(String columnLabel) throws SQLException {
return delegate.getNCharacterStream(columnLabel);
}
@Override
public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException {
delegate.updateNCharacterStream(columnIndex, x, length);
}
@Override
public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException {
delegate.updateNCharacterStream(columnLabel, reader, length);
}
@Override
public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException {
delegate.updateAsciiStream(columnIndex, x, length);
}
@Override
public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException {
delegate.updateBinaryStream(columnIndex, x, length);
}
@Override
public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException {
delegate.updateCharacterStream(columnIndex, x, length);
}
@Override
public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException {
delegate.updateAsciiStream(columnLabel, x, length);
}
@Override
public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException {
delegate.updateBinaryStream(columnLabel, x, length);
}
@Override
public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException {
delegate.updateCharacterStream(columnLabel, reader, length);
}
@Override
public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException {
delegate.updateBlob(columnIndex, inputStream, length);
}
@Override
public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException {
delegate.updateBlob(columnLabel, inputStream, length);
}
@Override
public void updateClob(int columnIndex, Reader reader, long length) throws SQLException {
delegate.updateClob(columnIndex, reader, length);
}
@Override
public void updateClob(String columnLabel, Reader reader, long length) throws SQLException {
delegate.updateClob(columnLabel, reader, length);
}
@Override
public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException {
delegate.updateNClob(columnIndex, reader, length);
}
@Override
public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException {
delegate.updateNClob(columnLabel, reader, length);
}
@Override
public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException {
delegate.updateNCharacterStream(columnIndex, x);
}
@Override
public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException {
delegate.updateNCharacterStream(columnLabel, reader);
}
@Override
public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException {
delegate.updateAsciiStream(columnIndex, x);
}
@Override
public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException {
delegate.updateBinaryStream(columnIndex, x);
}
@Override
public void updateCharacterStream(int columnIndex, Reader x) throws SQLException {
delegate.updateCharacterStream(columnIndex, x);
}
@Override
public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException {
delegate.updateAsciiStream(columnLabel, x);
}
@Override
public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException {
delegate.updateBinaryStream(columnLabel, x);
}
@Override
public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException {
delegate.updateCharacterStream(columnLabel, reader);
}
@Override
public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException {
delegate.updateBlob(columnIndex, inputStream);
}
@Override
public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException {
delegate.updateBlob(columnLabel, inputStream);
}
@Override
public void updateClob(int columnIndex, Reader reader) throws SQLException {
delegate.updateClob(columnIndex, reader);
}
@Override
public void updateClob(String columnLabel, Reader reader) throws SQLException {
delegate.updateClob(columnLabel, reader);
}
@Override
public void updateNClob(int columnIndex, Reader reader) throws SQLException {
delegate.updateNClob(columnIndex, reader);
}
@Override
public void updateNClob(String columnLabel, Reader reader) throws SQLException {
delegate.updateNClob(columnLabel, reader);
}
// Java 7+ methods, implemented poorly using Java 6... :(
//@Override
public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
//return delegate.getObject(columnIndex, type);
return type.cast(delegate.getObject(columnIndex));
}
//@Override
public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
//return delegate.getObject(columnLabel, type);
return type.cast(delegate.getObject(columnLabel));
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return delegate.unwrap(iface);
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return delegate.isWrapperFor(iface);
}
}

View File

@ -0,0 +1,60 @@
package com.moparisthebest.jdbc;
import javax.naming.Context;
import java.io.Closeable;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
public class TryClose { // tries to close certain object types
public static void tryClose(ResultSet obj) {
if (obj == null)
return;
try {
obj.close();
} catch (Throwable e) {
// ignore...
}
}
public static void tryClose(Context obj) {
if (obj == null)
return;
try {
obj.close();
} catch (Throwable e) {
// ignore...
}
}
public static void tryClose(Connection obj) {
if (obj == null)
return;
try {
obj.close();
} catch (Throwable e) {
// ignore...
}
}
public static void tryClose(Statement obj) {
if (obj == null)
return;
try {
obj.close();
} catch (Throwable e) {
// ignore...
}
}
public static void tryClose(Closeable obj) {
if (obj == null)
return;
try {
obj.close();
} catch (Throwable e) {
// ignore...
}
}
}

View File

@ -0,0 +1,403 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $Header:$
*/
package com.moparisthebest.jdbc;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Types;
import java.util.HashMap;
import java.util.Map;
/**
* Currently contains all types of type mappings. Implemented using singleton pattern.
*/
public final class TypeMappingsFactory {
/* @todo: refactor! */
private static TypeMappingsFactory _instance;
private static Class<?> XMLBEANS_STRING_ENUM_ABSTRACT_BASE = null;
static {
try {
XMLBEANS_STRING_ENUM_ABSTRACT_BASE = Class.forName("org.apache.xmlbeans.StringEnumAbstractBase");
} catch (ClassNotFoundException e) {
// not an error, just means XmlBeans is not available
}
}
/**
* Get an instance of this class.
* @return TypeMappingsFactory instance.
*/
public static TypeMappingsFactory getInstance() {
if (_instance == null) {
_instance = new TypeMappingsFactory();
}
return _instance;
}
public static final int TYPE_UNKNOWN = 0;
static final int TYPE_BYTE = 1;
static final int TYPE_SHORT = 2;
static final int TYPE_INT = 3;
static final int TYPE_LONG = 4;
static final int TYPE_FLOAT = 5;
static final int TYPE_DOUBLE = 6;
static final int TYPE_BOOLEAN = 7;
static final int TYPE_BYTE_OBJ = 8;
static final int TYPE_SHORT_OBJ = 9;
static final int TYPE_INT_OBJ = 10;
static final int TYPE_LONG_OBJ = 11;
static final int TYPE_FLOAT_OBJ = 12;
static final int TYPE_DOUBLE_OBJ = 13;
static final int TYPE_BOOLEAN_OBJ = 14;
static final int TYPE_BIG_DECIMAL = 15;
static final int TYPE_STRING = 16;
static final int TYPE_BYTES = 17;
static final int TYPE_SQLDATE = 18;
static final int TYPE_TIME = 19;
static final int TYPE_TIMESTAMP = 20;
static final int TYPE_STREAM = 21;
static final int TYPE_READER = 22;
static final int TYPE_CLOB = 23;
static final int TYPE_BLOB = 24;
static final int TYPE_ARRAY = 25;
static final int TYPE_REF = 26;
static final int TYPE_DATE = 27;
static final int TYPE_CALENDAR = 28;
static final int TYPE_STRUCT = 29;
static final int TYPE_XMLBEAN_ENUM = 30;
static final int TYPE_MAX = 31;
private Map<Class, Object> _primitiveDefaults;
//
// keys in this map are the class of the method's return type,
// values are the set of constants defined above all prefixed with
// TYPE_
//
private Map<Class, Integer> _typeMap;
private Map<Class, Integer> _typeSqlMap;
/**
* Map a string version of sql type to sql type (java.sql.Types).
* example: "INTEGER" maps to java.sql.Types.INTEGER
*/
private Map<String, Integer> _typeSqlNameMap;
private static Method _methodMapGet;
/**
* Constructor
*/
TypeMappingsFactory() {
_primitiveDefaults = new HashMap<Class, Object>();
_primitiveDefaults.put(Boolean.TYPE, Boolean.FALSE);
_primitiveDefaults.put(Integer.TYPE, new Integer(0));
_primitiveDefaults.put(Long.TYPE, new Long(0));
_primitiveDefaults.put(Byte.TYPE, new Byte((byte) 0));
_primitiveDefaults.put(Short.TYPE, new Short((short) 0));
_primitiveDefaults.put(Character.TYPE, new Character('\u0000'));
_primitiveDefaults.put(Float.TYPE, new Float(0.0f));
_primitiveDefaults.put(Double.TYPE, new Double(0.0d));
// Class to internal enum
_typeMap = new HashMap<Class, Integer>(TYPE_MAX * 2);
_typeMap.put(Boolean.TYPE, new Integer(TYPE_BOOLEAN));
_typeMap.put(Integer.TYPE, new Integer(TYPE_INT));
_typeMap.put(Long.TYPE, new Integer(TYPE_LONG));
_typeMap.put(Byte.TYPE, new Integer(TYPE_BYTE));
_typeMap.put(Short.TYPE, new Integer(TYPE_SHORT));
_typeMap.put(Float.TYPE, new Integer(TYPE_FLOAT));
_typeMap.put(Double.TYPE, new Integer(TYPE_DOUBLE));
_typeMap.put(Boolean.class, new Integer(TYPE_BOOLEAN_OBJ));
_typeMap.put(Integer.class, new Integer(TYPE_INT_OBJ));
_typeMap.put(Long.class, new Integer(TYPE_LONG_OBJ));
_typeMap.put(Byte.class, new Integer(TYPE_BYTE_OBJ));
_typeMap.put(Short.class, new Integer(TYPE_SHORT_OBJ));
_typeMap.put(Float.class, new Integer(TYPE_FLOAT_OBJ));
_typeMap.put(Double.class, new Integer(TYPE_DOUBLE_OBJ));
_typeMap.put(String.class, new Integer(TYPE_STRING));
_typeMap.put(java.math.BigDecimal.class, new Integer(TYPE_BIG_DECIMAL));
_typeMap.put(byte[].class, new Integer(TYPE_BYTES));
_typeMap.put(java.sql.Timestamp.class, new Integer(TYPE_TIMESTAMP));
_typeMap.put(java.sql.Time.class, new Integer(TYPE_TIME));
_typeMap.put(java.sql.Date.class, new Integer(TYPE_SQLDATE));
_typeMap.put(java.sql.Ref.class, new Integer(TYPE_REF));
_typeMap.put(Blob.class, new Integer(TYPE_BLOB));
_typeMap.put(Clob.class, new Integer(TYPE_CLOB));
_typeMap.put(java.sql.Array.class, new Integer(TYPE_ARRAY));
_typeMap.put(java.sql.Struct.class, new Integer(TYPE_STRUCT));
_typeMap.put(java.io.Reader.class, new Integer(TYPE_READER));
_typeMap.put(java.io.InputStream.class, new Integer(TYPE_STREAM));
_typeMap.put(java.util.Date.class, new Integer(TYPE_DATE));
_typeMap.put(java.util.Calendar.class, new Integer(TYPE_CALENDAR));
_typeMap.put(java.util.GregorianCalendar.class, new Integer(TYPE_CALENDAR));
if (XMLBEANS_STRING_ENUM_ABSTRACT_BASE != null) {
_typeMap.put(XMLBEANS_STRING_ENUM_ABSTRACT_BASE, new Integer(TYPE_XMLBEAN_ENUM));
}
// Class to java.sql.Types
_typeSqlMap = new HashMap<Class, Integer>(TYPE_MAX * 2);
_typeSqlMap.put(Boolean.TYPE, new Integer(Types.BOOLEAN));
_typeSqlMap.put(Integer.TYPE, new Integer(Types.INTEGER));
_typeSqlMap.put(Long.TYPE, new Integer(Types.BIGINT));
_typeSqlMap.put(Byte.TYPE, new Integer(Types.TINYINT));
_typeSqlMap.put(Short.TYPE, new Integer(Types.SMALLINT));
_typeSqlMap.put(Float.TYPE, new Integer(Types.REAL));
_typeSqlMap.put(Double.TYPE, new Integer(Types.DOUBLE));
_typeSqlMap.put(Boolean.class, new Integer(Types.BOOLEAN));
_typeSqlMap.put(Integer.class, new Integer(Types.INTEGER));
_typeSqlMap.put(Long.class, new Integer(Types.BIGINT));
_typeSqlMap.put(Byte.class, new Integer(Types.TINYINT));
_typeSqlMap.put(Short.class, new Integer(Types.SMALLINT));
_typeSqlMap.put(Float.class, new Integer(Types.REAL));
_typeSqlMap.put(Double.class, new Integer(Types.DOUBLE));
_typeSqlMap.put(String.class, new Integer(Types.VARCHAR));
_typeSqlMap.put(java.math.BigDecimal.class, new Integer(Types.DECIMAL));
_typeSqlMap.put(byte[].class, new Integer(Types.VARBINARY));
_typeSqlMap.put(java.sql.Timestamp.class, new Integer(Types.TIMESTAMP));
_typeSqlMap.put(java.sql.Time.class, new Integer(Types.TIME));
_typeSqlMap.put(java.sql.Date.class, new Integer(Types.DATE));
_typeSqlMap.put(java.sql.Ref.class, new Integer(Types.REF));
_typeSqlMap.put(Blob.class, new Integer(Types.BLOB));
_typeSqlMap.put(Clob.class, new Integer(Types.CLOB));
_typeSqlMap.put(java.sql.Array.class, new Integer(Types.ARRAY));
_typeSqlMap.put(java.sql.Struct.class, new Integer(Types.STRUCT));
_typeSqlMap.put(java.util.Date.class, new Integer(Types.TIMESTAMP));
_typeSqlMap.put(java.util.Calendar.class, new Integer(Types.TIMESTAMP));
_typeSqlMap.put(java.util.GregorianCalendar.class, new Integer(Types.TIMESTAMP));
if (XMLBEANS_STRING_ENUM_ABSTRACT_BASE != null) {
_typeSqlMap.put(XMLBEANS_STRING_ENUM_ABSTRACT_BASE, new Integer(Types.VARCHAR));
}
// String to java.sql.Types
_typeSqlNameMap = new HashMap<String, Integer>(TYPE_MAX * 2);
_typeSqlNameMap.put("BIT", new Integer(Types.BIT));
_typeSqlNameMap.put("TINYINT", new Integer(Types.TINYINT));
_typeSqlNameMap.put("SMALLINT", new Integer(Types.SMALLINT));
_typeSqlNameMap.put("INTEGER", new Integer(Types.INTEGER));
_typeSqlNameMap.put("BIGINT", new Integer(Types.BIGINT));
_typeSqlNameMap.put("FLOAT", new Integer(Types.REAL));
_typeSqlNameMap.put("REAL", new Integer(Types.REAL));
_typeSqlNameMap.put("DOUBLE", new Integer(Types.DOUBLE));
_typeSqlNameMap.put("NUMERIC", new Integer(Types.NUMERIC));
_typeSqlNameMap.put("DECIMAL", new Integer(Types.DECIMAL));
_typeSqlNameMap.put("CHAR", new Integer(Types.CHAR));
_typeSqlNameMap.put("VARCHAR", new Integer(Types.VARCHAR));
_typeSqlNameMap.put("LONGVARCHAR", new Integer(Types.LONGVARCHAR));
_typeSqlNameMap.put("DATE", new Integer(Types.DATE));
_typeSqlNameMap.put("TIME", new Integer(Types.TIME));
_typeSqlNameMap.put("TIMESTAMP", new Integer(Types.TIMESTAMP));
_typeSqlNameMap.put("BINARY", new Integer(Types.BINARY));
_typeSqlNameMap.put("VARBINARY", new Integer(Types.VARBINARY));
_typeSqlNameMap.put("LONGVARBINARY", new Integer(Types.LONGVARBINARY));
_typeSqlNameMap.put("NULL", new Integer(Types.NULL));
_typeSqlNameMap.put("OTHER", new Integer(Types.OTHER));
_typeSqlNameMap.put("JAVA_OBJECT", new Integer(Types.JAVA_OBJECT));
_typeSqlNameMap.put("DISTINCT", new Integer(Types.DISTINCT));
_typeSqlNameMap.put("STRUCT", new Integer(Types.STRUCT));
_typeSqlNameMap.put("ARRAY", new Integer(Types.ARRAY));
_typeSqlNameMap.put("BLOB", new Integer(Types.BLOB));
_typeSqlNameMap.put("CLOB", new Integer(Types.CLOB));
_typeSqlNameMap.put("REF", new Integer(Types.REF));
_typeSqlNameMap.put("DATALINK", new Integer(Types.DATALINK));
_typeSqlNameMap.put("BOOLEAN", new Integer(Types.BOOLEAN));
// some JAVA synonyms
_typeSqlNameMap.put("BYTE", new Integer(Types.TINYINT));
_typeSqlNameMap.put("SHORT", new Integer(Types.SMALLINT));
_typeSqlNameMap.put("INT", new Integer(Types.INTEGER));
_typeSqlNameMap.put("LONG", new Integer(Types.BIGINT));
// cache the Map.get method for efficiency
try {
_methodMapGet = Map.class.getMethod("get", new Class[]{Object.class});
} catch (NoSuchMethodException e) {
throw new MapperException("Can not find java.util.Map.get(Object) method");
}
}
/**
* Convert a type string to its SQL Type int value.
* @param type A String containing the SQL type name.
* @return The SQL type, TYPE_UNKNOWN if cannot convert.
*/
public int convertStringToSQLType(String type) {
if (_typeSqlNameMap.containsKey(type.toUpperCase())) {
return _typeSqlNameMap.get(type.toUpperCase());
}
return TYPE_UNKNOWN;
}
/**
* Get the SQL type of a class, start at top level class an check all super classes until match is found.
* @param classType Class to get SQL type of.
* @return Types.OTHER if cannot find SQL type.
*/
public int getSqlType(Class classType) {
final Class origType = classType;
while (classType != null) {
Integer type = _typeSqlMap.get(classType);
if (type != null) {
return type.intValue();
}
classType = classType.getSuperclass();
}
//
// special check for blobs/clobs they are interfaces not derived from
//
if (Blob.class.isAssignableFrom(origType)) {
return _typeSqlMap.get(Blob.class).intValue();
} else if (Clob.class.isAssignableFrom(origType)) {
return _typeSqlMap.get(Clob.class).intValue();
}
return Types.OTHER;
}
/**
* Get the SQL type for an object.
* @param o Object to get SQL type of.
* @return SQL type of the object, Types.OTHER if cannot classify.
*/
public int getSqlType(Object o) {
if (null == o) {
return Types.NULL;
}
return getSqlType(o.getClass());
}
/**
*
* @param val
* @param args
* @return the type
* @throws IllegalAccessException
* @throws java.lang.reflect.InvocationTargetException
*/
public Object lookupType(Object val, Object[] args)
throws IllegalAccessException, InvocationTargetException
{
return _methodMapGet.invoke(val, args);
}
/**
* Get the type id (defined by this class) for the given class.
* @param classType Class to get type of.
* @return Type id of class.
*/
public int getTypeId(Class classType) {
final Class origType = classType;
while (null != classType) {
Integer typeObj = (Integer) _typeMap.get(classType);
if (null != typeObj) {
return typeObj.intValue();
}
classType = classType.getSuperclass();
}
//
// special check for blobs/clobs they are interfaces not derived from
//
if (Blob.class.isAssignableFrom(origType)) {
return _typeMap.get(Blob.class).intValue();
} else if (Clob.class.isAssignableFrom(origType)) {
return _typeMap.get(Clob.class).intValue();
}
return TYPE_UNKNOWN;
}
/**
* Returns a primitive legal value as opposed to null if type is primitive.
* @param type type to get null value for.
* @return null value for specifed type.
*/
public Object fixNull(Class type) {
return type.isPrimitive() ? _primitiveDefaults.get(type) : null;
}
/**
* Create an Object array for the given array.
*
* @param o An array.
* @return A new object array.
*/
public static Object[] toObjectArray(Object o) {
Class clas = o.getClass().getComponentType();
if (null == clas) return null;
Object[] arr;
if (clas == Boolean.TYPE) {
boolean[] src = (boolean[]) o;
arr = new Object[src.length];
for (int i = 0; i < src.length; i++)
arr[i] = new Boolean(src[i]);
} else if (clas == Character.TYPE) {
char[] src = (char[]) o;
arr = new Object[src.length];
for (int i = 0; i < src.length; i++)
arr[i] = new Character(src[i]);
} else if (clas == Byte.TYPE) {
byte[] src = (byte[]) o;
arr = new Object[src.length];
for (int i = 0; i < src.length; i++)
arr[i] = new Byte(src[i]);
} else if (clas == Short.TYPE) {
short[] src = (short[]) o;
arr = new Object[src.length];
for (int i = 0; i < src.length; i++)
arr[i] = new Short(src[i]);
} else if (clas == Integer.TYPE) {
int[] src = (int[]) o;
arr = new Object[src.length];
for (int i = 0; i < src.length; i++)
arr[i] = new Integer(src[i]);
} else if (clas == Long.TYPE) {
long[] src = (long[]) o;
arr = new Object[src.length];
for (int i = 0; i < src.length; i++)
arr[i] = new Long(src[i]);
} else if (clas == Float.TYPE) {
float[] src = (float[]) o;
arr = new Object[src.length];
for (int i = 0; i < src.length; i++)
arr[i] = new Float(src[i]);
} else if (clas == Double.TYPE) {
double[] src = (double[]) o;
arr = new Object[src.length];
for (int i = 0; i < src.length; i++)
arr[i] = new Double(src[i]);
} else {
arr = (Object[]) o;
}
return arr;
}
}

View File

@ -0,0 +1,242 @@
package com.moparisthebest.jdbc;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import static com.moparisthebest.jdbc.TryClose.tryClose;
public abstract class UpdateableDTO implements Finishable {
private boolean finished = false;
private Map<String, Object> changes = null;
private String tableName;
private String whereClause;
public static final String YES = "Y";
public static final String NO = "N";
/**
* Will always return YES or NO from this class, so they CAN be compared with object equality '==' instead of '.equals()'
* @param bool
* @return
*/
public static String booleanToString(boolean bool){
return bool ? YES : NO;
}
public static boolean changed(Object oldValue, Object newValue){
return oldValue != newValue && ((oldValue != null && !oldValue.equals(newValue)) || !newValue.equals(oldValue));
}
public static <K, E> Object[] getUpdate(final StringBuilder sb, final Map<K, E> changes, final String tableName, final String whereClause){
if(changes.isEmpty())
return new Object[0];
sb.append("UPDATE ").append(tableName).append(" SET ");
int count = -1;
Object[] objectsToBind = new Object[changes.size()];
boolean notFirst = false;
for (Map.Entry<K, E> column : changes.entrySet()) {
if (column.getKey() == null) continue;
if (notFirst) sb.append(",");
else notFirst = true;
sb.append(column.getKey()).append("=?");
objectsToBind[++count] = column.getValue();
}
if(whereClause != null)
sb.append(" ").append(whereClause);
//System.out.println("updateRow: "+sb);
return objectsToBind;
}
public static <K, E> Object[] getInsert(final StringBuilder sb, final Map<K, E> changes, final String tableName){
if(changes.isEmpty())
return new Object[0];
sb.append("INSERT INTO ").append(tableName).append(" (");
int count = -1;
Object[] objectsToBind = new Object[changes.size()];
boolean notFirst = false;
for (Map.Entry<K, E> column : changes.entrySet()) {
if (column.getKey() == null) continue;
if (notFirst) sb.append(",");
else notFirst = true;
sb.append(column.getKey());
objectsToBind[++count] = column.getValue();
}
sb.append(") VALUES (?");
for(int x = 1; x < objectsToBind.length; ++x)
sb.append(",?");
sb.append(")");
//System.out.println("insertRow: "+sb);
return objectsToBind;
}
public static <K, E> int updateRow(final Connection conn, final Map<K, E> changes, final String tableName, final String whereClause, final Object... additionalBindObjects) throws SQLException {
StringBuilder sb = new StringBuilder();
Object[] objectsToBind = getUpdate(sb, changes, tableName, whereClause);
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sb.toString());
QueryMapper.bindStatement(ps, objectsToBind, additionalBindObjects == null ? new Object[0] : additionalBindObjects);
return ps.executeUpdate();
} finally {
tryClose(ps);
}
}
public static <K, E> int updateRow(final QueryMapper qm, final Map<K, E> changes, final String tableName, final String whereClause, final Object... additionalBindObjects) throws SQLException {
StringBuilder sb = new StringBuilder();
Object[] objectsToBind = getUpdate(sb, changes, tableName, whereClause);
return qm.executeUpdate(sb.toString(), objectsToBind, additionalBindObjects == null ? new Object[0] : additionalBindObjects);
}
public static <K, E> int insertRow(final Connection conn, final Map<K, E> changes, final String tableName) throws SQLException {
StringBuilder sb = new StringBuilder();
Object[] objectsToBind = getInsert(sb, changes, tableName);
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sb.toString());
QueryMapper.bindStatement(ps, objectsToBind);
return ps.executeUpdate();
} finally {
tryClose(ps);
}
}
public static <K, E> int insertRow(final QueryMapper qm, final Map<K, E> changes, final String tableName) throws SQLException {
StringBuilder sb = new StringBuilder();
Object[] objectsToBind = getInsert(sb, changes, tableName);
return qm.executeUpdate(sb.toString(), objectsToBind);
}
public static <K, E> int deleteRow(final Connection conn, final String tableName, final String whereClause, final Object... additionalBindObjects) throws SQLException {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(String.format("DELETE FROM %s %s", tableName, whereClause == null ? "" : whereClause));
if(additionalBindObjects != null)
QueryMapper.bindStatement(ps, additionalBindObjects);
return ps.executeUpdate();
} finally {
tryClose(ps);
}
}
public static <K, E> int deleteRow(final QueryMapper qm, final String tableName, final String whereClause, final Object... additionalBindObjects) throws SQLException {
return qm.executeUpdate(String.format("DELETE FROM %s %s", tableName, whereClause == null ? "" : whereClause), additionalBindObjects == null ? new Object[0] : additionalBindObjects);
}
protected UpdateableDTO(String tableName, String whereClause) {
setTableName(tableName);
this.whereClause = whereClause;
}
protected String getTableName() {
return tableName;
}
protected void setTableName(String tableName) {
if(tableName == null)
throw new NullPointerException("tableName can never be null! Insert, update, or delete would never work!");
this.tableName = tableName;
}
protected String getWhereClause() {
return whereClause;
}
protected void setWhereClause(String whereClause) {
this.whereClause = whereClause;
}
protected final void change(String columnName, boolean oldValue, boolean newValue) {
change(columnName, booleanToString(oldValue), booleanToString(newValue));
}
/**
* Right now this is NOT thread-safe, if this class is to be used concurrently, it needs synchronized
*
* This never saves the ORIGINAL value, so if you change a certain column to something new, then change it back
* to the original, it is still counted as a change. The way to fix this would be another Map<String, Object>
* of ORIGINAL values, but I'm not sure this is desired.
*
* @param columnName
* @param newValue
*/
protected final boolean change(String columnName, Object oldValue, Object newValue) {
if(finished && changed(oldValue, newValue)){
/*
System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++");
System.out.println("before: "+this);
System.out.printf("changing column '%s' from '%s' to '%s'\n", columnName, oldValue, newValue);
new Exception("Stack trace").printStackTrace(System.out);
System.out.println("----------------------------------------------");
*/
if (changes == null)
changes = new HashMap<String, Object>();
changes.put(columnName, newValue);
return true;
}
return false;
}
public boolean hasChanged() {
return changes != null && !changes.isEmpty(); // not null would probably suffice?
}
public int updateRow(Connection conn) throws SQLException {
if (!hasChanged())
return 0;
return updateRow(conn, changes, this.tableName, this.whereClause, this.getAdditionalBindObjects());
}
public int updateRow(QueryMapper qm) throws SQLException {
if (!hasChanged())
return 0;
return updateRow(qm, changes, this.tableName, this.whereClause, this.getAdditionalBindObjects());
}
public int insertRow(Connection conn) throws SQLException {
if (!hasChanged())
return 0;
return insertRow(conn, changes, this.tableName);
}
public int insertRow(QueryMapper qm) throws SQLException {
if (!hasChanged())
return 0;
return insertRow(qm, changes, this.tableName);
}
public int deleteRow(Connection conn) throws SQLException {
return deleteRow(conn, this.tableName, this.whereClause, this.getAdditionalBindObjects());
}
public int deleteRow(QueryMapper qm) throws SQLException {
return deleteRow(qm, this.tableName, this.whereClause, this.getAdditionalBindObjects());
}
@Override
public void finish(ResultSet rs) throws SQLException {
this.finished = true;
}
/**
* You will almost always want to return some objects here for your where clause
*
* if you need to bind a single null, return new Object[]{null}, otherwise nothing will be binded
* if you only need to bind a single non-null object, return that object here
* if you need to bind multiple objects, return an Object[] or a Collection
*/
public abstract Object getAdditionalBindObjects();
@Override
public String toString() {
return "UpdateableDTO{" +
"finished=" + finished +
", changes=" + changes +
'}';
}
}

View File

@ -85,6 +85,7 @@
<module>beehive-jdbc-control</module>
<module>beehive-ejb-control</module>
<module>beehive-jms-control</module>
<module>beehive-jdbc-mapper</module>
</modules>
<dependencyManagement>
<dependencies>
@ -227,6 +228,7 @@
<source>1.5</source>
<target>1.5</target>
<debug>true</debug>
<!--compilerArgument>-Xlint:unchecked</compilerArgument-->
</configuration>
</plugin>
<plugin>