mirror of
https://github.com/moparisthebest/JdbcMapper
synced 2024-11-24 18:02:18 -05:00
Fix QueryMapper toResultSet and insertGetGeneratedKeyType to use PreparedStatementFactory and become un-ambiguous
This commit is contained in:
parent
278e99e894
commit
a490154334
@ -93,47 +93,19 @@ public class CachingQueryMapper extends QueryMapper {
|
||||
}
|
||||
|
||||
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;
|
||||
return getPreparedStatement(sql, defaultPsf);
|
||||
}
|
||||
|
||||
protected PreparedStatement getInsertPreparedStatement(final String sql, final int autoGeneratedKeys) throws SQLException {
|
||||
/**
|
||||
* This could perhaps end up caching something it shouldn't, as psf could return a different PreparedStatement
|
||||
* for a given sql, we are going to assume this would never happen, if it could, don't use CachingQueryMapper or
|
||||
* override this method, whatever you want.
|
||||
*/
|
||||
protected PreparedStatement getPreparedStatement(final String sql, final PreparedStatementFactory psf) throws SQLException {
|
||||
PreparedStatement ps = cache.get(sql);
|
||||
if (ps == null) {
|
||||
//System.out.println("cache miss");
|
||||
ps = conn.prepareStatement(sql, autoGeneratedKeys);
|
||||
cache.put(sql, ps);
|
||||
}
|
||||
//else System.out.println("cache hit");
|
||||
return ps;
|
||||
}
|
||||
|
||||
protected PreparedStatement getInsertPreparedStatement(final String sql, final int[] columnIndexes) throws SQLException {
|
||||
PreparedStatement ps = cache.get(sql);
|
||||
if (ps == null) {
|
||||
//System.out.println("cache miss");
|
||||
ps = conn.prepareStatement(sql, columnIndexes);
|
||||
cache.put(sql, ps);
|
||||
}
|
||||
//else System.out.println("cache hit");
|
||||
return ps;
|
||||
}
|
||||
|
||||
protected PreparedStatement getInsertPreparedStatement(final String sql, final String[] columnNames) throws SQLException {
|
||||
PreparedStatement ps = cache.get(sql);
|
||||
if (ps == null) {
|
||||
//System.out.println("cache miss");
|
||||
ps = conn.prepareStatement(sql, columnNames);
|
||||
ps = psf.prepareStatement(conn, sql);
|
||||
cache.put(sql, ps);
|
||||
}
|
||||
//else System.out.println("cache hit");
|
||||
@ -171,34 +143,19 @@ public class CachingQueryMapper extends QueryMapper {
|
||||
|
||||
@Override
|
||||
public Long insertGetGeneratedKey(String sql, Object... bindObjects) throws SQLException {
|
||||
return super.insertGetGeneratedKey(getInsertPreparedStatement(sql, Statement.RETURN_GENERATED_KEYS), bindObjects);
|
||||
return super.insertGetGeneratedKey(getPreparedStatement(sql, getSingleColumnPreparedStatementFactory()), bindObjects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T insertGetGeneratedKeyType(String sql, TypeReference<T> typeReference, Object... bindObjects) throws SQLException {
|
||||
return super.insertGetGeneratedKeyType(getInsertPreparedStatement(sql, Statement.RETURN_GENERATED_KEYS), typeReference, bindObjects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T insertGetGeneratedKeyType(String sql, int[] columnIndexes, TypeReference<T> typeReference, Object... bindObjects) throws SQLException {
|
||||
return super.insertGetGeneratedKeyType(getInsertPreparedStatement(sql, columnIndexes), typeReference, bindObjects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T insertGetGeneratedKeyType(String sql, String[] columnNames, TypeReference<T> typeReference, Object... bindObjects) throws SQLException {
|
||||
return super.insertGetGeneratedKeyType(getInsertPreparedStatement(sql, columnNames), typeReference, bindObjects);
|
||||
public <T> T insertGetGeneratedKeyType(String sql, final PreparedStatementFactory psf, TypeReference<T> typeReference, Object... bindObjects) throws SQLException {
|
||||
return super.insertGetGeneratedKeyType(getPreparedStatement(sql, psf), typeReference, 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, int rsType, int rsConcurrency, Object... bindObjects) throws SQLException {
|
||||
return super.toResultSet(getPreparedStatement(sql,rsType,rsConcurrency), bindObjects);
|
||||
public ResultSet toResultSet(final String sql, final PreparedStatementFactory psf, final Object... bindObjects) throws SQLException {
|
||||
return super.toResultSet(getPreparedStatement(sql, psf), bindObjects);
|
||||
}
|
||||
|
||||
// DO NOT EDIT BELOW THIS LINE, OR CHANGE THIS COMMENT, CODE AUTOMATICALLY GENERATED BY genQueryMapper.sh
|
||||
|
@ -293,8 +293,8 @@ public class ListQueryMapper extends QueryMapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultSet toResultSet(String sql, int rsType, int rsConcurrency, Object... bindObjects) throws SQLException {
|
||||
return delegate.toResultSet(prepareSql(sql, bindObjects), rsType, rsConcurrency, bindObjects);
|
||||
public ResultSet toResultSet(String sql, PreparedStatementFactory psf, Object... bindObjects) throws SQLException {
|
||||
return delegate.toResultSet(prepareSql(sql, bindObjects), psf, bindObjects);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -308,13 +308,8 @@ public class ListQueryMapper extends QueryMapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T insertGetGeneratedKeyType(String sql, int[] columnIndexes, TypeReference<T> typeReference, Object... bindObjects) throws SQLException {
|
||||
return delegate.insertGetGeneratedKeyType(prepareSql(sql, bindObjects), columnIndexes, typeReference, bindObjects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T insertGetGeneratedKeyType(String sql, String[] columnNames, TypeReference<T> typeReference, Object... bindObjects) throws SQLException {
|
||||
return delegate.insertGetGeneratedKeyType(prepareSql(sql, bindObjects), columnNames, typeReference, bindObjects);
|
||||
public <T> T insertGetGeneratedKeyType(String sql, PreparedStatementFactory psf, TypeReference<T> typeReference, Object... bindObjects) throws SQLException {
|
||||
return delegate.insertGetGeneratedKeyType(prepareSql(sql, bindObjects), psf, typeReference, bindObjects);
|
||||
}
|
||||
|
||||
// DO NOT EDIT BELOW THIS LINE, OR CHANGE THIS COMMENT, CODE AUTOMATICALLY GENERATED BY genQueryMapper.sh
|
||||
|
@ -165,19 +165,9 @@ public class NullQueryMapper extends QueryMapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T insertGetGeneratedKeyType(String sql, int[] columnIndexes, TypeReference<T> typeReference, Object... bindObjects) {
|
||||
public <T> T insertGetGeneratedKeyType(String sql, PreparedStatementFactory psf, TypeReference<T> typeReference, Object... bindObjects) {
|
||||
try {
|
||||
return delegate.insertGetGeneratedKeyType(sql, columnIndexes, typeReference, bindObjects);
|
||||
} catch (Throwable e) {
|
||||
if (verbose) e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T insertGetGeneratedKeyType(String sql, String[] columnNames, TypeReference<T> typeReference, Object... bindObjects) {
|
||||
try {
|
||||
return delegate.insertGetGeneratedKeyType(sql, columnNames, typeReference, bindObjects);
|
||||
return delegate.insertGetGeneratedKeyType(sql, psf, typeReference, bindObjects);
|
||||
} catch (Throwable e) {
|
||||
if (verbose) e.printStackTrace();
|
||||
}
|
||||
@ -269,9 +259,9 @@ public class NullQueryMapper extends QueryMapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultSet toResultSet(String sql, int rsType, int rsConcurrency, Object... bindObjects) throws SQLException {
|
||||
public ResultSet toResultSet(String sql, PreparedStatementFactory psf, Object... bindObjects) {
|
||||
try {
|
||||
return delegate.toResultSet(sql, rsType, rsConcurrency, bindObjects);
|
||||
return delegate.toResultSet(sql, psf, bindObjects);
|
||||
} catch (Throwable e) {
|
||||
if (verbose) e.printStackTrace();
|
||||
}
|
||||
|
@ -0,0 +1,9 @@
|
||||
package com.moparisthebest.jdbc;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public interface PreparedStatementFactory {
|
||||
PreparedStatement prepareStatement(Connection conn, String sql) throws SQLException;
|
||||
}
|
@ -25,7 +25,32 @@ public class QueryMapper implements JdbcMapper {
|
||||
|
||||
protected static final int[] ORACLE_SINGLE_COLUMN_INDEX = new int[]{1};
|
||||
|
||||
//IFJAVA8_START
|
||||
public static final PreparedStatementFactory oracleSingleColumnPsf = (conn, sql) -> conn.prepareStatement(sql, ORACLE_SINGLE_COLUMN_INDEX);
|
||||
public static final PreparedStatementFactory standardReturnGeneratedKeysPsf = (conn, sql) -> conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
|
||||
public static final PreparedStatementFactory defaultPsf = Connection::prepareStatement;
|
||||
//IFJAVA8_END
|
||||
|
||||
/*IFJAVA6_START
|
||||
public static final PreparedStatementFactory oracleSingleColumnPsf = new PreparedStatementFactory() {
|
||||
@Override
|
||||
public PreparedStatement prepareStatement(Connection conn, String sql) throws SQLException {
|
||||
return conn.prepareStatement(sql, ORACLE_SINGLE_COLUMN_INDEX);
|
||||
}
|
||||
};
|
||||
public static final PreparedStatementFactory standardReturnGeneratedKeysPsf = new PreparedStatementFactory() {
|
||||
@Override
|
||||
public PreparedStatement prepareStatement(Connection conn, String sql) throws SQLException {
|
||||
return conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
|
||||
}
|
||||
};
|
||||
public static final PreparedStatementFactory defaultPsf = new PreparedStatementFactory() {
|
||||
@Override
|
||||
public PreparedStatement prepareStatement(Connection conn, String sql) throws SQLException {
|
||||
return conn.prepareStatement(sql);
|
||||
}
|
||||
};
|
||||
|
||||
private static final Charset UTF_8 = Charset.forName("UTF-8");
|
||||
IFJAVA6_END*/
|
||||
|
||||
@ -332,20 +357,27 @@ public class QueryMapper implements JdbcMapper {
|
||||
}
|
||||
}
|
||||
|
||||
private Boolean oracleDatabase = null;
|
||||
public Long insertGetGeneratedKey(final String sql, final Object... bindObjects) throws SQLException {
|
||||
private PreparedStatementFactory singleColumnPsf = null;
|
||||
protected PreparedStatementFactory getSingleColumnPreparedStatementFactory() {
|
||||
// this single function is somewhat database specific
|
||||
// sqlite/ms-sql/mysql works with either Statement.RETURN_GENERATED_KEYS or int[]{1}
|
||||
// oracle requires int[]{1} instead, failing on Statement.RETURN_GENERATED_KEYS
|
||||
// postgre requires Statement.RETURN_GENERATED_KEYS instead, failing on int[]{1}
|
||||
|
||||
// so we lazily cache oracleDatabase just in this one function
|
||||
if(oracleDatabase == null)
|
||||
oracleDatabase = OptimalInList.isWrapperFor(conn, OptimalInList.oracleConnection);
|
||||
if(singleColumnPsf == null) {
|
||||
if(OptimalInList.isWrapperFor(conn, OptimalInList.oracleConnection))
|
||||
singleColumnPsf = oracleSingleColumnPsf;
|
||||
else
|
||||
singleColumnPsf = standardReturnGeneratedKeysPsf;
|
||||
}
|
||||
return singleColumnPsf;
|
||||
}
|
||||
|
||||
public Long insertGetGeneratedKey(final String sql, final Object... bindObjects) throws SQLException {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
ps = oracleDatabase ? conn.prepareStatement(sql, ORACLE_SINGLE_COLUMN_INDEX) : conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
|
||||
ps = getSingleColumnPreparedStatementFactory().prepareStatement(conn, sql);
|
||||
return this.insertGetGeneratedKey(ps, bindObjects);
|
||||
} finally {
|
||||
tryClose(ps);
|
||||
@ -353,29 +385,13 @@ public class QueryMapper implements JdbcMapper {
|
||||
}
|
||||
|
||||
public <T> T insertGetGeneratedKeyType(final String sql, final TypeReference<T> typeReference, final Object... bindObjects) throws SQLException {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
|
||||
return this.insertGetGeneratedKeyType(ps, typeReference, bindObjects);
|
||||
} finally {
|
||||
tryClose(ps);
|
||||
}
|
||||
return insertGetGeneratedKeyType(sql, standardReturnGeneratedKeysPsf, typeReference, bindObjects);
|
||||
}
|
||||
|
||||
public <T> T insertGetGeneratedKeyType(final String sql, final int[] columnIndexes, final TypeReference<T> typeReference, final Object... bindObjects) throws SQLException {
|
||||
public <T> T insertGetGeneratedKeyType(final String sql, final PreparedStatementFactory psf, final TypeReference<T> typeReference, final Object... bindObjects) throws SQLException {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
ps = conn.prepareStatement(sql, columnIndexes);
|
||||
return this.insertGetGeneratedKeyType(ps, typeReference, bindObjects);
|
||||
} finally {
|
||||
tryClose(ps);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> T insertGetGeneratedKeyType(final String sql, final String[] columnNames, final TypeReference<T> typeReference, final Object... bindObjects) throws SQLException {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
ps = conn.prepareStatement(sql, columnNames);
|
||||
ps = psf.prepareStatement(conn, sql);
|
||||
return this.insertGetGeneratedKeyType(ps, typeReference, bindObjects);
|
||||
} finally {
|
||||
tryClose(ps);
|
||||
@ -422,17 +438,17 @@ public class QueryMapper implements JdbcMapper {
|
||||
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(final String sql, final Object... bindObjects) throws SQLException {
|
||||
return toResultSet(sql, defaultPsf, bindObjects);
|
||||
}
|
||||
|
||||
public ResultSet toResultSet(String sql, int rsType, int rsConcurrency, final Object... bindObjects) throws SQLException {
|
||||
public ResultSet toResultSet(final String sql, final PreparedStatementFactory psf, final Object... bindObjects) throws SQLException {
|
||||
// works with StatementClosingResultSet
|
||||
boolean error = true;
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
ps = conn.prepareStatement(sql, rsType, rsConcurrency);
|
||||
ps = psf.prepareStatement(conn, sql);
|
||||
rs = this.toResultSet(ps, bindObjects);
|
||||
error = false;
|
||||
return new StatementClosingResultSet(rs, ps);
|
||||
|
Loading…
Reference in New Issue
Block a user