Author: wspeirs Date: Tue Mar 27 01:39:27 2012 New Revision: 1305706 URL: http://svn.apache.org/viewvc?rev=1305706&view=rev Log: - Applied DBUTILS88v2 patch - Cleaned up a few things CheckStyle and FindBugs were unhappy about
Modified: commons/proper/dbutils/trunk/src/main/java/org/apache/commons/dbutils/AbstractQueryRunner.java commons/proper/dbutils/trunk/src/main/java/org/apache/commons/dbutils/AsyncQueryRunner.java commons/proper/dbutils/trunk/src/test/java/org/apache/commons/dbutils/AsyncQueryRunnerTest.java Modified: commons/proper/dbutils/trunk/src/main/java/org/apache/commons/dbutils/AbstractQueryRunner.java URL: http://svn.apache.org/viewvc/commons/proper/dbutils/trunk/src/main/java/org/apache/commons/dbutils/AbstractQueryRunner.java?rev=1305706&r1=1305705&r2=1305706&view=diff ============================================================================== --- commons/proper/dbutils/trunk/src/main/java/org/apache/commons/dbutils/AbstractQueryRunner.java (original) +++ commons/proper/dbutils/trunk/src/main/java/org/apache/commons/dbutils/AbstractQueryRunner.java Tue Mar 27 01:39:27 2012 @@ -33,20 +33,21 @@ import java.util.Arrays; import javax.sql.DataSource; /** - * The base class for QueryRunner & AsyncQueryRunner. - * This class is thread safe. + * The base class for QueryRunner & AsyncQueryRunner. This class is thread safe. + * * @since 1.4 (mostly extracted from QueryRunner) */ public abstract class AbstractQueryRunner { /** - * Is {@link ParameterMetaData#getParameterType(int)} broken (have we tried it yet)? + * Is {@link ParameterMetaData#getParameterType(int)} broken (have we tried + * it yet)? */ private volatile boolean pmdKnownBroken = false; /** * The DataSource to retrieve connections from. */ - protected final DataSource ds; + private final DataSource ds; /** * Default constructor, sets pmdKnownBroken to false and ds to null. @@ -57,9 +58,13 @@ public abstract class AbstractQueryRunne /** * Constructor to control the use of <code>ParameterMetaData</code>. - * @param pmdKnownBroken Some drivers don't support {@link ParameterMetaData#getParameterType(int) }; - * if <code>pmdKnownBroken</code> is set to true, we won't even try it; if false, we'll try it, - * and if it breaks, we'll remember not to use it again. + * + * @param pmdKnownBroken + * Some drivers don't support + * {@link ParameterMetaData#getParameterType(int) }; if + * <code>pmdKnownBroken</code> is set to true, we won't even try + * it; if false, we'll try it, and if it breaks, we'll remember + * not to use it again. */ public AbstractQueryRunner(boolean pmdKnownBroken) { this.pmdKnownBroken = pmdKnownBroken; @@ -67,25 +72,31 @@ public abstract class AbstractQueryRunne } /** - * Constructor to provide a <code>DataSource</code>. - * Methods that do not take a <code>Connection</code> parameter will - * retrieve connections from this <code>DataSource</code>. + * Constructor to provide a <code>DataSource</code>. Methods that do not + * take a <code>Connection</code> parameter will retrieve connections from + * this <code>DataSource</code>. * - * @param ds The <code>DataSource</code> to retrieve connections from. + * @param ds + * The <code>DataSource</code> to retrieve connections from. */ public AbstractQueryRunner(DataSource ds) { this.ds = ds; } /** - * Constructor to provide a <code>DataSource</code> and control the use of <code>ParameterMetaData</code>. - * Methods that do not take a <code>Connection</code> parameter will retrieve connections from this + * Constructor to provide a <code>DataSource</code> and control the use of + * <code>ParameterMetaData</code>. Methods that do not take a + * <code>Connection</code> parameter will retrieve connections from this * <code>DataSource</code>. * - * @param ds The <code>DataSource</code> to retrieve connections from. - * @param pmdKnownBroken Some drivers don't support {@link ParameterMetaData#getParameterType(int) }; - * if <code>pmdKnownBroken</code> is set to true, we won't even try it; if false, we'll try it, - * and if it breaks, we'll remember not to use it again. + * @param ds + * The <code>DataSource</code> to retrieve connections from. + * @param pmdKnownBroken + * Some drivers don't support + * {@link ParameterMetaData#getParameterType(int) }; if + * <code>pmdKnownBroken</code> is set to true, we won't even try + * it; if false, we'll try it, and if it breaks, we'll remember + * not to use it again. */ public AbstractQueryRunner(DataSource ds, boolean pmdKnownBroken) { this.pmdKnownBroken = pmdKnownBroken; @@ -95,8 +106,7 @@ public abstract class AbstractQueryRunne /** * Returns the <code>DataSource</code> this runner is using. * <code>QueryRunner</code> methods always call this method to get the - * <code>DataSource</code> so subclasses can provide specialized - * behavior. + * <code>DataSource</code> so subclasses can provide specialized behavior. * * @return DataSource the runner is using */ @@ -105,11 +115,14 @@ public abstract class AbstractQueryRunne } /** - * Some drivers don't support {@link ParameterMetaData#getParameterType(int) }; - * if <code>pmdKnownBroken</code> is set to true, we won't even try it; if false, we'll try it, - * and if it breaks, we'll remember not to use it again. + * Some drivers don't support + * {@link ParameterMetaData#getParameterType(int) }; if + * <code>pmdKnownBroken</code> is set to true, we won't even try it; if + * false, we'll try it, and if it breaks, we'll remember not to use it + * again. * - * @return the flag to skip (or not) {@link ParameterMetaData#getParameterType(int) } + * @return the flag to skip (or not) + * {@link ParameterMetaData#getParameterType(int) } * @since 1.4 */ public boolean isPmdKnownBroken() { @@ -120,51 +133,60 @@ public abstract class AbstractQueryRunne * Factory method that creates and initializes a * <code>PreparedStatement</code> object for the given SQL. * <code>QueryRunner</code> methods always call this method to prepare - * statements for them. Subclasses can override this method to provide - * special PreparedStatement configuration if needed. This implementation + * statements for them. Subclasses can override this method to provide + * special PreparedStatement configuration if needed. This implementation * simply calls <code>conn.prepareStatement(sql)</code>. * - * @param conn The <code>Connection</code> used to create the - * <code>PreparedStatement</code> - * @param sql The SQL statement to prepare. + * @param conn + * The <code>Connection</code> used to create the + * <code>PreparedStatement</code> + * @param sql + * The SQL statement to prepare. * @return An initialized <code>PreparedStatement</code>. - * @throws SQLException if a database access error occurs + * @throws SQLException + * if a database access error occurs */ protected PreparedStatement prepareStatement(Connection conn, String sql) - throws SQLException { + throws SQLException { return conn.prepareStatement(sql); } /** - * Factory method that creates and initializes a - * <code>Connection</code> object. <code>QueryRunner</code> methods - * always call this method to retrieve connections from its DataSource. - * Subclasses can override this method to provide - * special <code>Connection</code> configuration if needed. This - * implementation simply calls <code>ds.getConnection()</code>. + * Factory method that creates and initializes a <code>Connection</code> + * object. <code>QueryRunner</code> methods always call this method to + * retrieve connections from its DataSource. Subclasses can override this + * method to provide special <code>Connection</code> configuration if + * needed. This implementation simply calls <code>ds.getConnection()</code>. * * @return An initialized <code>Connection</code>. - * @throws SQLException if a database access error occurs + * @throws SQLException + * if a database access error occurs * @since DbUtils 1.1 */ protected Connection prepareConnection() throws SQLException { if (this.getDataSource() == null) { - throw new SQLException("QueryRunner requires a DataSource to be " + - "invoked in this way, or a Connection should be passed in"); + throw new SQLException( + "QueryRunner requires a DataSource to be " + + "invoked in this way, or a Connection should be passed in"); } return this.getDataSource().getConnection(); } /** - * Fill the <code>PreparedStatement</code> replacement parameters with - * the given objects. - * @param stmt PreparedStatement to fill - * @param params Query replacement parameters; <code>null</code> is a valid - * value to pass in. - * @throws SQLException if a database access error occurs + * Fill the <code>PreparedStatement</code> replacement parameters with the + * given objects. + * + * @param stmt + * PreparedStatement to fill + * @param params + * Query replacement parameters; <code>null</code> is a valid + * value to pass in. + * @throws SQLException + * if a database access error occurs */ - public void fillStatement(PreparedStatement stmt, Object... params) throws SQLException { + public void fillStatement(PreparedStatement stmt, Object... params) + throws SQLException { // check the parameter count, if we can ParameterMetaData pmd = null; @@ -189,14 +211,15 @@ public abstract class AbstractQueryRunne stmt.setObject(i + 1, params[i]); } else { // VARCHAR works with many drivers regardless - // of the actual column type. Oddly, NULL and + // of the actual column type. Oddly, NULL and // OTHER don't work with Oracle's drivers. int sqlType = Types.VARCHAR; if (!pmdKnownBroken) { try { /* - * It's not possible for pmdKnownBroken to change from true to false, - * (once true, always true) so pmd cannot be null here. + * It's not possible for pmdKnownBroken to change from + * true to false, (once true, always true) so pmd cannot + * be null here. */ sqlType = pmd.getParameterType(i + 1); } catch (SQLException e) { @@ -236,11 +259,14 @@ public abstract class AbstractQueryRunne try { value = method.invoke(bean, new Object[0]); } catch (InvocationTargetException e) { - throw new RuntimeException("Couldn't invoke method: " + method, e); + throw new RuntimeException("Couldn't invoke method: " + method, + e); } catch (IllegalArgumentException e) { - throw new RuntimeException("Couldn't invoke method with 0 arguments: " + method, e); + throw new RuntimeException( + "Couldn't invoke method with 0 arguments: " + method, e); } catch (IllegalAccessException e) { - throw new RuntimeException("Couldn't invoke method: " + method, e); + throw new RuntimeException("Couldn't invoke method: " + method, + e); } params[i] = value; } @@ -251,26 +277,33 @@ public abstract class AbstractQueryRunne * Fill the <code>PreparedStatement</code> replacement parameters with the * given object's bean property values. * - * @param stmt PreparedStatement to fill - * @param bean A JavaBean object - * @param propertyNames An ordered array of property names (these should match the - * getters/setters); this gives the order to insert values in the - * statement - * @throws SQLException If a database access error occurs + * @param stmt + * PreparedStatement to fill + * @param bean + * A JavaBean object + * @param propertyNames + * An ordered array of property names (these should match the + * getters/setters); this gives the order to insert values in the + * statement + * @throws SQLException + * If a database access error occurs */ - public void fillStatementWithBean(PreparedStatement stmt, Object bean, String... propertyNames) throws SQLException { + public void fillStatementWithBean(PreparedStatement stmt, Object bean, + String... propertyNames) throws SQLException { PropertyDescriptor[] descriptors; try { descriptors = Introspector.getBeanInfo(bean.getClass()) - .getPropertyDescriptors(); + .getPropertyDescriptors(); } catch (IntrospectionException e) { - throw new RuntimeException("Couldn't introspect bean " + bean.getClass().toString(), e); + throw new RuntimeException("Couldn't introspect bean " + + bean.getClass().toString(), e); } PropertyDescriptor[] sorted = new PropertyDescriptor[propertyNames.length]; for (int i = 0; i < propertyNames.length; i++) { String propertyName = propertyNames[i]; if (propertyName == null) { - throw new NullPointerException("propertyName can't be null: " + i); + throw new NullPointerException("propertyName can't be null: " + + i); } boolean found = false; for (int j = 0; j < descriptors.length; j++) { @@ -292,18 +325,22 @@ public abstract class AbstractQueryRunne /** * Throws a new exception with a more informative error message. * - * @param cause The original exception that will be chained to the new - * exception when it's rethrown. - * - * @param sql The query that was executing when the exception happened. + * @param cause + * The original exception that will be chained to the new + * exception when it's rethrown. + * + * @param sql + * The query that was executing when the exception happened. + * + * @param params + * The query replacement parameters; <code>null</code> is a valid + * value to pass in. * - * @param params The query replacement parameters; <code>null</code> is a - * valid value to pass in. - * - * @throws SQLException if a database access error occurs + * @throws SQLException + * if a database access error occurs */ protected void rethrow(SQLException cause, String sql, Object... params) - throws SQLException { + throws SQLException { String causeMessage = cause.getMessage(); if (causeMessage == null) { @@ -329,14 +366,15 @@ public abstract class AbstractQueryRunne } /** - * Wrap the <code>ResultSet</code> in a decorator before processing it. - * This implementation returns the <code>ResultSet</code> it is given - * without any decoration. + * Wrap the <code>ResultSet</code> in a decorator before processing it. This + * implementation returns the <code>ResultSet</code> it is given without any + * decoration. * * <p> * Often, the implementation of this method can be done in an anonymous * inner class like this: * </p> + * * <pre> * QueryRunner run = new QueryRunner() { * protected ResultSet wrap(ResultSet rs) { @@ -345,8 +383,9 @@ public abstract class AbstractQueryRunne * }; * </pre> * - * @param rs The <code>ResultSet</code> to decorate; never - * <code>null</code>. + * @param rs + * The <code>ResultSet</code> to decorate; never + * <code>null</code>. * @return The <code>ResultSet</code> wrapped in some decorator. */ protected ResultSet wrap(ResultSet rs) { @@ -354,11 +393,14 @@ public abstract class AbstractQueryRunne } /** - * Close a <code>Connection</code>. This implementation avoids closing if - * null and does <strong>not</strong> suppress any exceptions. Subclasses + * Close a <code>Connection</code>. This implementation avoids closing if + * null and does <strong>not</strong> suppress any exceptions. Subclasses * can override to provide special handling like logging. - * @param conn Connection to close - * @throws SQLException if a database access error occurs + * + * @param conn + * Connection to close + * @throws SQLException + * if a database access error occurs * @since DbUtils 1.1 */ protected void close(Connection conn) throws SQLException { @@ -366,11 +408,14 @@ public abstract class AbstractQueryRunne } /** - * Close a <code>Statement</code>. This implementation avoids closing if - * null and does <strong>not</strong> suppress any exceptions. Subclasses + * Close a <code>Statement</code>. This implementation avoids closing if + * null and does <strong>not</strong> suppress any exceptions. Subclasses * can override to provide special handling like logging. - * @param stmt Statement to close - * @throws SQLException if a database access error occurs + * + * @param stmt + * Statement to close + * @throws SQLException + * if a database access error occurs * @since DbUtils 1.1 */ protected void close(Statement stmt) throws SQLException { @@ -378,11 +423,14 @@ public abstract class AbstractQueryRunne } /** - * Close a <code>ResultSet</code>. This implementation avoids closing if - * null and does <strong>not</strong> suppress any exceptions. Subclasses + * Close a <code>ResultSet</code>. This implementation avoids closing if + * null and does <strong>not</strong> suppress any exceptions. Subclasses * can override to provide special handling like logging. - * @param rs ResultSet to close - * @throws SQLException if a database access error occurs + * + * @param rs + * ResultSet to close + * @throws SQLException + * if a database access error occurs * @since DbUtils 1.1 */ protected void close(ResultSet rs) throws SQLException { Modified: commons/proper/dbutils/trunk/src/main/java/org/apache/commons/dbutils/AsyncQueryRunner.java URL: http://svn.apache.org/viewvc/commons/proper/dbutils/trunk/src/main/java/org/apache/commons/dbutils/AsyncQueryRunner.java?rev=1305706&r1=1305705&r2=1305706&view=diff ============================================================================== --- commons/proper/dbutils/trunk/src/main/java/org/apache/commons/dbutils/AsyncQueryRunner.java (original) +++ commons/proper/dbutils/trunk/src/main/java/org/apache/commons/dbutils/AsyncQueryRunner.java Tue Mar 27 01:39:27 2012 @@ -36,6 +36,18 @@ import javax.sql.DataSource; public class AsyncQueryRunner extends AbstractQueryRunner { private final ExecutorService executorService; + private final QueryRunner queryRunner; + + /** + * Constructor for AsyncQueryRunner which uses a provided ExecutorService and underlying QueryRunner. + * + * @param executorService the {@code ExecutorService} instance used to run JDBC invocations concurrently. + * @param queryRunner the {@code QueryRunner} instance to use for the queries. + */ + public AsyncQueryRunner(ExecutorService executorService, QueryRunner queryRunner) { + this.executorService = executorService; + this.queryRunner = queryRunner; + } /** * Constructor for AsyncQueryRunner. @@ -47,6 +59,7 @@ public class AsyncQueryRunner extends Ab } /** + * @deprecated Use {@link #AsyncQueryRunner(ExecutorService, QueryRunner)} instead. * Constructor for AsyncQueryRunner that controls the use of <code>ParameterMetaData</code>. * * @param pmdKnownBroken Some drivers don't support {@link java.sql.ParameterMetaData#getParameterType(int) }; @@ -54,11 +67,13 @@ public class AsyncQueryRunner extends Ab * and if it breaks, we'll remember not to use it again. * @param executorService the {@code ExecutorService} instance used to run JDBC invocations concurrently. */ + @Deprecated public AsyncQueryRunner(boolean pmdKnownBroken, ExecutorService executorService) { this(null, pmdKnownBroken, executorService); } /** + * @deprecated Use {@link #AsyncQueryRunner(ExecutorService, QueryRunner)} instead. * Constructor for AsyncQueryRunner that takes a <code>DataSource</code>. * * Methods that do not take a <code>Connection</code> parameter will retrieve connections from this @@ -67,11 +82,13 @@ public class AsyncQueryRunner extends Ab * @param ds The <code>DataSource</code> to retrieve connections from. * @param executorService the {@code ExecutorService} instance used to run JDBC invocations concurrently. */ + @Deprecated public AsyncQueryRunner(DataSource ds, ExecutorService executorService) { this(ds, false, executorService); } /** + * @deprecated Use {@link #AsyncQueryRunner(ExecutorService, QueryRunner)} instead. * Constructor for AsyncQueryRunner that take a <code>DataSource</code> and controls the use of <code>ParameterMetaData</code>. * Methods that do not take a <code>Connection</code> parameter will retrieve connections from this * <code>DataSource</code>. @@ -82,14 +99,18 @@ public class AsyncQueryRunner extends Ab * and if it breaks, we'll remember not to use it again. * @param executorService the {@code ExecutorService} instance used to run JDBC invocations concurrently. */ + @Deprecated public AsyncQueryRunner(DataSource ds, boolean pmdKnownBroken, ExecutorService executorService) { super(ds, pmdKnownBroken); this.executorService = executorService; + this.queryRunner = new QueryRunner(ds, pmdKnownBroken); } /** + * @deprecated No longer used by this class. Will be removed in a future version. * Class that encapsulates the continuation for batch calls. */ + @Deprecated protected class BatchCallableStatement implements Callable<int[]> { private final String sql; private final Object[][] params; @@ -109,7 +130,7 @@ public class AsyncQueryRunner extends Ab */ public BatchCallableStatement(String sql, Object[][] params, Connection conn, boolean closeConn, PreparedStatement ps) { this.sql = sql; - this.params = params; + this.params = params.clone(); this.conn = conn; this.closeConn = closeConn; this.ps = ps; @@ -151,8 +172,15 @@ public class AsyncQueryRunner extends Ab * @return A <code>Future</code> which returns the number of rows updated per statement. * @throws SQLException if a database access error occurs */ - public Future<int[]> batch(Connection conn, String sql, Object[][] params) throws SQLException { - return executorService.submit(this.batch(conn, false, sql, params)); + public Future<int[]> batch(final Connection conn, final String sql, final Object[][] params) throws SQLException { + return executorService.submit(new Callable<int[]>() { + + @Override + public int[] call() throws Exception { + return queryRunner.batch(conn, sql, params); + } + + }); } /** @@ -167,60 +195,15 @@ public class AsyncQueryRunner extends Ab * @return A <code>Future</code> which returns the number of rows updated per statement. * @throws SQLException if a database access error occurs */ - public Future<int[]> batch(String sql, Object[][] params) throws SQLException { - Connection conn = this.prepareConnection(); + public Future<int[]> batch(final String sql, final Object[][] params) throws SQLException { + return executorService.submit(new Callable<int[]>() { - return executorService.submit(this.batch(conn, true, sql, params)); - } - - /** - * Creates a continuation for a batch call, and returns it in a <code>Callable</code>. - * @param conn The connection to use for the batch call. - * @param closeConn True if the connection should be closed, false otherwise. - * @param sql The SQL statement to execute. - * @param params An array of query replacement parameters. Each row in - * this array is one set of batch replacement values. - * @return A <code>Callable</code> which returns the number of rows updated per statement. - * @throws SQLException If there are database or parameter errors. - */ - private Callable<int[]> batch(Connection conn, boolean closeConn, String sql, Object[][] params) throws SQLException { - if (conn == null) { - throw new SQLException("Null connection"); - } - - if (sql == null) { - if (closeConn) { - close(conn); + @Override + public int[] call() throws Exception { + return queryRunner.batch(sql, params); } - throw new SQLException("Null SQL statement"); - } - if (params == null) { - if (closeConn) { - close(conn); - } - throw new SQLException("Null parameters. If parameters aren't need, pass an empty array."); - } - - PreparedStatement stmt = null; - Callable<int[]> ret = null; - try { - stmt = this.prepareStatement(conn, sql); - - for (int i = 0; i < params.length; i++) { - this.fillStatement(stmt, params[i]); - stmt.addBatch(); - } - - ret = new BatchCallableStatement(sql, params, conn, closeConn, stmt); - - } catch (SQLException e) { - close(stmt); - close(conn); - this.rethrow(e, sql, (Object[])params); - } - - return ret; + }); } /** @@ -289,56 +272,6 @@ public class AsyncQueryRunner extends Ab } /** - * Creates a continuation for a query call, and returns it in a <code>Callable</code>. - * @param conn The connection to use for the query call. - * @param closeConn True if the connection should be closed, false otherwise. - * @param sql The SQL statement to execute. - * @param params An array of query replacement parameters. Each row in - * this array is one set of query replacement values. - * @return A <code>Callable</code> which returns the result of the query call. - * @throws SQLException If there are database or parameter errors. - */ - private <T> Callable<T> query(Connection conn, boolean closeConn, String sql, ResultSetHandler<T> rsh, Object... params) - throws SQLException { - PreparedStatement stmt = null; - Callable<T> ret = null; - - if (conn == null) { - throw new SQLException("Null connection"); - } - - if (sql == null) { - if (closeConn) { - close(conn); - } - throw new SQLException("Null SQL statement"); - } - - if (rsh == null) { - if (closeConn) { - close(conn); - } - throw new SQLException("Null ResultSetHandler"); - } - - try { - stmt = this.prepareStatement(conn, sql); - this.fillStatement(stmt, params); - - ret = new QueryCallableStatement<T>(conn, closeConn, stmt, rsh, sql, params); - - } catch (SQLException e) { - close(stmt); - if (closeConn) { - close(conn); - } - this.rethrow(e, sql, params); - } - - return ret; - } - - /** * Execute an SQL SELECT query with replacement parameters. The * caller is responsible for closing the connection. * @param <T> The type of object that the handler returns @@ -349,8 +282,16 @@ public class AsyncQueryRunner extends Ab * @return A <code>Future</code> which returns the result of the query call. * @throws SQLException if a database access error occurs */ - public <T> Future<T> query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException { - return executorService.submit(this.<T>query(conn, false, sql, rsh, params)); + public <T> Future<T> query(final Connection conn, final String sql, final ResultSetHandler<T> rsh, final Object... params) + throws SQLException { + return executorService.submit(new Callable<T>() { + + @Override + public T call() throws Exception { + return queryRunner.query(conn, sql, rsh, params); + } + + }); } /** @@ -363,8 +304,15 @@ public class AsyncQueryRunner extends Ab * @return A <code>Future</code> which returns the result of the query call. * @throws SQLException if a database access error occurs */ - public <T> Future<T> query(Connection conn, String sql, ResultSetHandler<T> rsh) throws SQLException { - return executorService.submit(this.<T>query(conn, false, sql, rsh, (Object[]) null)); + public <T> Future<T> query(final Connection conn, final String sql, final ResultSetHandler<T> rsh) throws SQLException { + return executorService.submit(new Callable<T>() { + + @Override + public T call() throws Exception { + return queryRunner.query(conn, sql, rsh); + } + + }); } /** @@ -380,9 +328,15 @@ public class AsyncQueryRunner extends Ab * @return A <code>Future</code> which returns the result of the query call. * @throws SQLException if a database access error occurs */ - public <T> Future<T> query(String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException { - Connection conn = this.prepareConnection(); - return executorService.submit(this.<T>query(conn, true, sql, rsh, params)); + public <T> Future<T> query(final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException { + return executorService.submit(new Callable<T>() { + + @Override + public T call() throws Exception { + return queryRunner.query(sql, rsh, params); + } + + }); } /** @@ -397,14 +351,22 @@ public class AsyncQueryRunner extends Ab * @return A <code>Future</code> which returns the result of the query call. * @throws SQLException if a database access error occurs */ - public <T> Future<T> query(String sql, ResultSetHandler<T> rsh) throws SQLException { - Connection conn = this.prepareConnection(); - return executorService.submit(this.<T>query(conn, true, sql, rsh, (Object[]) null)); + public <T> Future<T> query(final String sql, final ResultSetHandler<T> rsh) throws SQLException { + return executorService.submit(new Callable<T>() { + + @Override + public T call() throws Exception { + return queryRunner.query(sql, rsh); + } + + }); } /** + * @deprecated No longer used by this class. Will be removed in a future version. * Class that encapsulates the continuation for update calls. */ + @Deprecated protected class UpdateCallableStatement implements Callable<Integer> { private final String sql; private final Object[] params; @@ -458,48 +420,6 @@ public class AsyncQueryRunner extends Ab } /** - * Creates a continuation for an update call, and returns it in a <code>Callable</code>. - * @param conn The connection to use for the update call. - * @param closeConn True if the connection should be closed, false otherwise. - * @param sql The SQL statement to execute. - * @param params An array of update replacement parameters. Each row in - * this array is one set of update replacement values. - * @return A <code>Callable</code> which returns the number of rows updated. - * @throws SQLException If there are database or parameter errors. - */ - private Callable<Integer> update(Connection conn, boolean closeConn, String sql, Object... params) throws SQLException { - PreparedStatement stmt = null; - Callable<Integer> ret = null; - - if (conn == null) { - throw new SQLException("Null connection"); - } - - if (sql == null) { - if (closeConn) { - close(conn); - } - throw new SQLException("Null SQL statement"); - } - - try { - stmt = this.prepareStatement(conn, sql); - this.fillStatement(stmt, params); - - ret = new UpdateCallableStatement(conn, closeConn, stmt, sql, params); - - } catch (SQLException e) { - close(stmt); - if (closeConn) { - close(conn); - } - this.rethrow(e, sql, params); - } - - return ret; - } - - /** * Execute an SQL INSERT, UPDATE, or DELETE query without replacement * parameters. * @@ -508,8 +428,15 @@ public class AsyncQueryRunner extends Ab * @return A <code>Future</code> which returns the number of rows updated. * @throws SQLException if a database access error occurs */ - public Future<Integer> update(Connection conn, String sql) throws SQLException { - return executorService.submit(this.update(conn, false, sql, (Object[]) null)); + public Future<Integer> update(final Connection conn, final String sql) throws SQLException { + return executorService.submit(new Callable<Integer>() { + + @Override + public Integer call() throws Exception { + return queryRunner.update(conn, sql); + } + + }); } /** @@ -522,8 +449,15 @@ public class AsyncQueryRunner extends Ab * @return A <code>Future</code> which returns the number of rows updated. * @throws SQLException if a database access error occurs */ - public Future<Integer> update(Connection conn, String sql, Object param) throws SQLException { - return executorService.submit(this.update(conn, false, sql, new Object[]{param})); + public Future<Integer> update(final Connection conn, final String sql, final Object param) throws SQLException { + return executorService.submit(new Callable<Integer>() { + + @Override + public Integer call() throws Exception { + return queryRunner.update(conn, sql, param); + } + + }); } /** @@ -535,8 +469,15 @@ public class AsyncQueryRunner extends Ab * @return A <code>Future</code> which returns the number of rows updated. * @throws SQLException if a database access error occurs */ - public Future<Integer> update(Connection conn, String sql, Object... params) throws SQLException { - return executorService.submit(this.update(conn, false, sql, params)); + public Future<Integer> update(final Connection conn, final String sql, final Object... params) throws SQLException { + return executorService.submit(new Callable<Integer>() { + + @Override + public Integer call() throws Exception { + return queryRunner.update(conn, sql, params); + } + + }); } /** @@ -550,9 +491,15 @@ public class AsyncQueryRunner extends Ab * @throws SQLException if a database access error occurs * @return A <code>Future</code> which returns the number of rows updated. */ - public Future<Integer> update(String sql) throws SQLException { - Connection conn = this.prepareConnection(); - return executorService.submit(this.update(conn, true, sql, (Object[]) null)); + public Future<Integer> update(final String sql) throws SQLException { + return executorService.submit(new Callable<Integer>() { + + @Override + public Integer call() throws Exception { + return queryRunner.update(sql); + } + + }); } /** @@ -567,9 +514,15 @@ public class AsyncQueryRunner extends Ab * @throws SQLException if a database access error occurs * @return A <code>Future</code> which returns the number of rows updated. */ - public Future<Integer> update(String sql, Object param) throws SQLException { - Connection conn = this.prepareConnection(); - return executorService.submit(this.update(conn, true, sql, new Object[]{param})); + public Future<Integer> update(final String sql, final Object param) throws SQLException { + return executorService.submit(new Callable<Integer>() { + + @Override + public Integer call() throws Exception { + return queryRunner.update(sql, param); + } + + }); } /** @@ -584,9 +537,15 @@ public class AsyncQueryRunner extends Ab * @throws SQLException if a database access error occurs * @return A <code>Future</code> which returns the number of rows updated. */ - public Future<Integer> update(String sql, Object... params) throws SQLException { - Connection conn = this.prepareConnection(); - return executorService.submit(this.update(conn, true, sql, params)); + public Future<Integer> update(final String sql, final Object... params) throws SQLException { + return executorService.submit(new Callable<Integer>() { + + @Override + public Integer call() throws Exception { + return queryRunner.update(sql, params); + } + + }); } } Modified: commons/proper/dbutils/trunk/src/test/java/org/apache/commons/dbutils/AsyncQueryRunnerTest.java URL: http://svn.apache.org/viewvc/commons/proper/dbutils/trunk/src/test/java/org/apache/commons/dbutils/AsyncQueryRunnerTest.java?rev=1305706&r1=1305705&r2=1305706&view=diff ============================================================================== --- commons/proper/dbutils/trunk/src/test/java/org/apache/commons/dbutils/AsyncQueryRunnerTest.java (original) +++ commons/proper/dbutils/trunk/src/test/java/org/apache/commons/dbutils/AsyncQueryRunnerTest.java Tue Mar 27 01:39:27 2012 @@ -28,6 +28,7 @@ import java.sql.ParameterMetaData; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.Future; @@ -71,9 +72,10 @@ public class AsyncQueryRunnerTest { private void callGoodBatch(Connection conn, Object[][] params) throws Exception { when(meta.getParameterCount()).thenReturn(2); Future<int[]> future = runner.batch(conn, "select * from blah where ? = ?", params); - verify(stmt, times(2)).addBatch(); future.get(); + + verify(stmt, times(2)).addBatch(); verify(stmt, times(1)).executeBatch(); verify(stmt, times(1)).close(); // make sure we closed the statement verify(conn, times(0)).close(); // make sure we closed the connection @@ -82,9 +84,10 @@ public class AsyncQueryRunnerTest { private void callGoodBatch(Object[][] params) throws Exception { when(meta.getParameterCount()).thenReturn(2); Future<int[]> future = runner.batch("select * from blah where ? = ?", params); - verify(stmt, times(2)).addBatch(); future.get(); + + verify(stmt, times(2)).addBatch(); verify(stmt, times(1)).executeBatch(); verify(stmt, times(1)).close(); // make sure we closed the statement verify(conn, times(1)).close(); // make sure we closed the connection @@ -129,9 +132,10 @@ public class AsyncQueryRunnerTest { try { future = runner.batch(sql, params); - verify(stmt, times(2)).addBatch(); - + future.get(); + + verify(stmt, times(2)).addBatch(); verify(stmt, times(1)).executeBatch(); verify(stmt, times(1)).close(); // make sure the statement is closed verify(conn, times(1)).close(); // make sure the connection is closed @@ -157,30 +161,30 @@ public class AsyncQueryRunnerTest { callBatchWithException("select * from blah where ? = ?", params); } - @Test(expected=SQLException.class) + @Test(expected=ExecutionException.class) public void testNullConnectionBatch() throws Exception { String[][] params = new String[][] { { "unit", "unit" }, { "test", "test" } }; when(meta.getParameterCount()).thenReturn(2); when(dataSource.getConnection()).thenReturn(null); - runner.batch("select * from blah where ? = ?", params); + runner.batch("select * from blah where ? = ?", params).get(); } - @Test(expected=SQLException.class) + @Test(expected=ExecutionException.class) public void testNullSqlBatch() throws Exception { String[][] params = new String[][] { { "unit", "unit" }, { "test", "test" } }; when(meta.getParameterCount()).thenReturn(2); - runner.batch(null, params); + runner.batch(null, params).get(); } - @Test(expected=SQLException.class) + @Test(expected=ExecutionException.class) public void testNullParamsArgBatch() throws Exception { when(meta.getParameterCount()).thenReturn(2); - runner.batch("select * from blah where ? = ?", null); + runner.batch("select * from blah where ? = ?", null).get(); } @Test @@ -296,26 +300,26 @@ public class AsyncQueryRunnerTest { callQueryWithException("unit", "test", "fail"); } - @Test(expected=SQLException.class) + @Test(expected=ExecutionException.class) public void testNullConnectionQuery() throws Exception { when(meta.getParameterCount()).thenReturn(2); when(dataSource.getConnection()).thenReturn(null); - runner.query("select * from blah where ? = ?", handler, "unit", "test"); + runner.query("select * from blah where ? = ?", handler, "unit", "test").get(); } - @Test(expected=SQLException.class) + @Test(expected=ExecutionException.class) public void testNullSqlQuery() throws Exception { when(meta.getParameterCount()).thenReturn(2); - runner.query(null, handler); + runner.query(null, handler).get(); } - @Test(expected=SQLException.class) + @Test(expected=ExecutionException.class) public void testNullHandlerQuery() throws Exception { when(meta.getParameterCount()).thenReturn(2); - runner.query("select * from blah where ? = ?", null); + runner.query("select * from blah where ? = ?", null).get(); } @Test @@ -430,19 +434,19 @@ public class AsyncQueryRunnerTest { callUpdateWithException("unit", "test", "fail"); } - @Test(expected=SQLException.class) + @Test(expected=ExecutionException.class) public void testNullConnectionUpdate() throws Exception { when(meta.getParameterCount()).thenReturn(2); when(dataSource.getConnection()).thenReturn(null); - runner.update("select * from blah where ? = ?", "unit", "test"); + runner.update("select * from blah where ? = ?", "unit", "test").get(); } - @Test(expected=SQLException.class) + @Test(expected=ExecutionException.class) public void testNullSqlUpdate() throws Exception { when(meta.getParameterCount()).thenReturn(2); - runner.update(null); + runner.update(null).get(); } @Test @@ -455,36 +459,9 @@ public class AsyncQueryRunnerTest { // // Random tests // - class MyBean { - private int a; - private double b; - private String c; - - public int getA() { return a; } - public void setA(int a) { this.a = a; } - public double getB() { return b; } - public void setB(double b) { this.b = b; } - public String getC() { return c; } - public void setC(String c) { this.c = c; } - } - - @Test - public void testFillStatementWithBean() throws Exception { - MyBean bean = new MyBean(); - when(meta.getParameterCount()).thenReturn(3); - runner.fillStatementWithBean(stmt, bean, new String[] { "a", "b", "c" }); - } - - @Test(expected=NullPointerException.class) - public void testFillStatementWithBeanNullNames() throws Exception { - MyBean bean = new MyBean(); - when(meta.getParameterCount()).thenReturn(3); - runner.fillStatementWithBean(stmt, bean, new String[] { "a", "b", null }); - } - - @Test(expected=SQLException.class) + @Test(expected=ExecutionException.class) public void testBadPrepareConnection() throws Exception { runner = new AsyncQueryRunner(Executors.newFixedThreadPool(1)); - runner.update("update blah set unit = test"); + runner.update("update blah set unit = test").get(); } }