You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2022/08/29 11:35:57 UTC

[commons-dbutils] branch master updated: Javadoc @link tags do not need to use a FQCN for classes in java.lang

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-dbutils.git


The following commit(s) were added to refs/heads/master by this push:
     new d8b498b  Javadoc @link tags do not need to use a FQCN for classes in java.lang
d8b498b is described below

commit d8b498b9136513e42c9efd6d04eac85f5531e2cb
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Mon Aug 29 07:35:54 2022 -0400

    Javadoc @link tags do not need to use a FQCN for classes in java.lang
---
 .../org/apache/commons/dbutils/QueryRunner.java    | 2000 ++++++++++----------
 1 file changed, 1000 insertions(+), 1000 deletions(-)

diff --git a/src/main/java/org/apache/commons/dbutils/QueryRunner.java b/src/main/java/org/apache/commons/dbutils/QueryRunner.java
index 13fd124..6a1aee1 100644
--- a/src/main/java/org/apache/commons/dbutils/QueryRunner.java
+++ b/src/main/java/org/apache/commons/dbutils/QueryRunner.java
@@ -1,1000 +1,1000 @@
-/*
- * 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.
- */
-package org.apache.commons.dbutils;
-
-import java.sql.CallableStatement;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.LinkedList;
-import java.util.List;
-import javax.sql.DataSource;
-
-/**
- * Executes SQL queries with pluggable strategies for handling
- * {@code ResultSet}s.  This class is thread safe.
- *
- * @see ResultSetHandler
- */
-public class QueryRunner extends AbstractQueryRunner {
-
-    /**
-     * Constructor for QueryRunner.
-     */
-    public QueryRunner() {
-    }
-
-    /**
-     * Constructor for QueryRunner that controls the use of {@code ParameterMetaData}.
-     *
-     * @param pmdKnownBroken Some drivers don't support {@link java.sql.ParameterMetaData#getParameterType(int) };
-     * if {@code pmdKnownBroken} 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 QueryRunner(final boolean pmdKnownBroken) {
-        super(pmdKnownBroken);
-    }
-
-    /**
-     * Constructor for QueryRunner that takes a {@code DataSource} to use.
-     *
-     * Methods that do not take a {@code Connection} parameter will retrieve connections from this
-     * {@code DataSource}.
-     *
-     * @param ds The {@code DataSource} to retrieve connections from.
-     */
-    public QueryRunner(final DataSource ds) {
-        super(ds);
-    }
-
-    /**
-     * Constructor for QueryRunner that takes a {@code StatementConfiguration} to configure statements when
-     * preparing them.
-     *
-     * @param stmtConfig The configuration to apply to statements when they are prepared.
-     */
-    public QueryRunner(final StatementConfiguration stmtConfig) {
-        super(stmtConfig);
-    }
-
-    /**
-     * Constructor for QueryRunner that takes a {@code DataSource} and controls the use of {@code ParameterMetaData}.
-     * Methods that do not take a {@code Connection} parameter will retrieve connections from this
-     * {@code DataSource}.
-     *
-     * @param ds The {@code DataSource} to retrieve connections from.
-     * @param pmdKnownBroken Some drivers don't support {@link java.sql.ParameterMetaData#getParameterType(int) };
-     * if {@code pmdKnownBroken} 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 QueryRunner(final DataSource ds, final boolean pmdKnownBroken) {
-        super(ds, pmdKnownBroken);
-    }
-
-    /**
-     * Constructor for QueryRunner that takes a {@code DataSource} to use and a {@code StatementConfiguration}.
-     *
-     * Methods that do not take a {@code Connection} parameter will retrieve connections from this
-     * {@code DataSource}.
-     *
-     * @param ds The {@code DataSource} to retrieve connections from.
-     * @param stmtConfig The configuration to apply to statements when they are prepared.
-     */
-    public QueryRunner(final DataSource ds, final StatementConfiguration stmtConfig) {
-        super(ds, stmtConfig);
-    }
-
-    /**
-     * Constructor for QueryRunner that takes a {@code DataSource}, a {@code StatementConfiguration}, and
-     * controls the use of {@code ParameterMetaData}.  Methods that do not take a {@code Connection} parameter
-     * will retrieve connections from this {@code DataSource}.
-     *
-     * @param ds The {@code DataSource} to retrieve connections from.
-     * @param pmdKnownBroken Some drivers don't support {@link java.sql.ParameterMetaData#getParameterType(int) };
-     * if {@code pmdKnownBroken} 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 stmtConfig The configuration to apply to statements when they are prepared.
-     */
-    public QueryRunner(final DataSource ds, final boolean pmdKnownBroken, final StatementConfiguration stmtConfig) {
-        super(ds, pmdKnownBroken, stmtConfig);
-    }
-
-    /**
-     * Execute a batch of SQL INSERT, UPDATE, or DELETE queries.
-     *
-     * @param conn The Connection to use to run the query.  The caller is
-     * responsible for closing this Connection.
-     * @param sql The SQL to execute.
-     * @param params An array of query replacement parameters.  Each row in
-     * this array is one set of batch replacement values.
-     * @return The number of rows updated per statement.
-     * @throws SQLException if a database access error occurs
-     * @since DbUtils 1.1
-     */
-    public int[] batch(final Connection conn, final String sql, final Object[][] params) throws SQLException {
-        return this.batch(conn, false, sql, params);
-    }
-
-    /**
-     * Execute a batch of SQL INSERT, UPDATE, or DELETE queries.  The
-     * {@code Connection} is retrieved from the {@code DataSource}
-     * set in the constructor.  This {@code Connection} must be in
-     * auto-commit mode or the update will not be saved.
-     *
-     * @param sql The SQL to execute.
-     * @param params An array of query replacement parameters.  Each row in
-     * this array is one set of batch replacement values.
-     * @return The number of rows updated per statement.
-     * @throws SQLException if a database access error occurs
-     * @since DbUtils 1.1
-     */
-    public int[] batch(final String sql, final Object[][] params) throws SQLException {
-        final Connection conn = this.prepareConnection();
-
-        return this.batch(conn, true, sql, params);
-    }
-
-    /**
-     * Calls update after checking the parameters to ensure nothing is null.
-     * @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 The number of rows updated in the batch.
-     * @throws SQLException If there are database or parameter errors.
-     */
-    private int[] batch(final Connection conn, final boolean closeConn, final String sql, final Object[][] params) throws SQLException {
-        if (conn == null) {
-            throw new SQLException("Null connection");
-        }
-
-        if (sql == null) {
-            if (closeConn) {
-                close(conn);
-            }
-            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;
-        int[] rows = null;
-        try {
-            stmt = this.prepareStatement(conn, sql);
-
-            for (final Object[] param : params) {
-                this.fillStatement(stmt, param);
-                stmt.addBatch();
-            }
-            rows = stmt.executeBatch();
-
-        } catch (final SQLException e) {
-            this.rethrow(e, sql, (Object[])params);
-        } finally {
-            close(stmt);
-            if (closeConn) {
-                close(conn);
-            }
-        }
-
-        return rows;
-    }
-
-    /**
-     * Execute an SQL SELECT query with a single replacement parameter. The
-     * caller is responsible for closing the connection.
-     * @param <T> The type of object that the handler returns
-     * @param conn The connection to execute the query in.
-     * @param sql The query to execute.
-     * @param param The replacement parameter.
-     * @param rsh The handler that converts the results into an object.
-     * @return The object returned by the handler.
-     * @throws SQLException if a database access error occurs
-     * @deprecated Use {@link #query(Connection, String, ResultSetHandler, Object...)}
-     */
-    @Deprecated
-    public <T> T query(final Connection conn, final String sql, final Object param, final ResultSetHandler<T> rsh) throws SQLException {
-        return this.<T>query(conn, false, sql, rsh, param);
-    }
-
-    /**
-     * 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
-     * @param conn The connection to execute the query in.
-     * @param sql The query to execute.
-     * @param params The replacement parameters.
-     * @param rsh The handler that converts the results into an object.
-     * @return The object returned by the handler.
-     * @throws SQLException if a database access error occurs
-     * @deprecated Use {@link #query(Connection,String,ResultSetHandler,Object...)} instead
-     */
-    @Deprecated
-    public <T> T query(final Connection conn, final String sql, final Object[] params, final ResultSetHandler<T> rsh) throws SQLException {
-        return this.<T>query(conn, false, sql, rsh, params);
-    }
-
-    /**
-     * 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
-     * @param conn The connection to execute the query in.
-     * @param sql The query to execute.
-     * @param rsh The handler that converts the results into an object.
-     * @param params The replacement parameters.
-     * @return The object returned by the handler.
-     * @throws SQLException if a database access error occurs
-     */
-    public <T> T query(final Connection conn, final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
-        return this.<T>query(conn, false, sql, rsh, params);
-    }
-
-    /**
-     * Execute an SQL SELECT query without any replacement parameters.  The
-     * caller is responsible for closing the connection.
-     * @param <T> The type of object that the handler returns
-     * @param conn The connection to execute the query in.
-     * @param sql The query to execute.
-     * @param rsh The handler that converts the results into an object.
-     * @return The object returned by the handler.
-     * @throws SQLException if a database access error occurs
-     */
-    public <T> T query(final Connection conn, final String sql, final ResultSetHandler<T> rsh) throws SQLException {
-        return this.<T>query(conn, false, sql, rsh, (Object[]) null);
-    }
-
-    /**
-     * Executes the given SELECT SQL with a single replacement parameter.
-     * The {@code Connection} is retrieved from the
-     * {@code DataSource} set in the constructor.
-     * @param <T> The type of object that the handler returns
-     * @param sql The SQL statement to execute.
-     * @param param The replacement parameter.
-     * @param rsh The handler used to create the result object from
-     * the {@code ResultSet}.
-     *
-     * @return An object generated by the handler.
-     * @throws SQLException if a database access error occurs
-     * @deprecated Use {@link #query(String, ResultSetHandler, Object...)}
-     */
-    @Deprecated
-    public <T> T query(final String sql, final Object param, final ResultSetHandler<T> rsh) throws SQLException {
-        final Connection conn = this.prepareConnection();
-
-        return this.<T>query(conn, true, sql, rsh, param);
-    }
-
-    /**
-     * Executes the given SELECT SQL query and returns a result object.
-     * The {@code Connection} is retrieved from the
-     * {@code DataSource} set in the constructor.
-     * @param <T> The type of object that the handler returns
-     * @param sql The SQL statement to execute.
-     * @param params Initialize the PreparedStatement's IN parameters with
-     * this array.
-     *
-     * @param rsh The handler used to create the result object from
-     * the {@code ResultSet}.
-     *
-     * @return An object generated by the handler.
-     * @throws SQLException if a database access error occurs
-     * @deprecated Use {@link #query(String, ResultSetHandler, Object...)}
-     */
-    @Deprecated
-    public <T> T query(final String sql, final Object[] params, final ResultSetHandler<T> rsh) throws SQLException {
-        final Connection conn = this.prepareConnection();
-
-        return this.<T>query(conn, true, sql, rsh, params);
-    }
-
-    /**
-     * Executes the given SELECT SQL query and returns a result object.
-     * The {@code Connection} is retrieved from the
-     * {@code DataSource} set in the constructor.
-     * @param <T> The type of object that the handler returns
-     * @param sql The SQL statement to execute.
-     * @param rsh The handler used to create the result object from
-     * the {@code ResultSet}.
-     * @param params Initialize the PreparedStatement's IN parameters with
-     * this array.
-     * @return An object generated by the handler.
-     * @throws SQLException if a database access error occurs
-     */
-    public <T> T query(final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
-        final Connection conn = this.prepareConnection();
-
-        return this.<T>query(conn, true, sql, rsh, params);
-    }
-
-    /**
-     * Executes the given SELECT SQL without any replacement parameters.
-     * The {@code Connection} is retrieved from the
-     * {@code DataSource} set in the constructor.
-     * @param <T> The type of object that the handler returns
-     * @param sql The SQL statement to execute.
-     * @param rsh The handler used to create the result object from
-     * the {@code ResultSet}.
-     *
-     * @return An object generated by the handler.
-     * @throws SQLException if a database access error occurs
-     */
-    public <T> T query(final String sql, final ResultSetHandler<T> rsh) throws SQLException {
-        final Connection conn = this.prepareConnection();
-
-        return this.<T>query(conn, true, sql, rsh, (Object[]) null);
-    }
-
-    /**
-     * Calls query after checking the parameters to ensure nothing is null.
-     * @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 batch replacement values.
-     * @return The results of the query.
-     * @throws SQLException If there are database or parameter errors.
-     */
-    private <T> T query(final Connection conn, final boolean closeConn, final String sql, final ResultSetHandler<T> rsh, final Object... params)
-            throws SQLException {
-        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");
-        }
-
-        Statement stmt = null;
-        ResultSet rs = null;
-        T result = null;
-
-        try {
-            if (params != null && params.length > 0) {
-                final PreparedStatement ps = this.prepareStatement(conn, sql);
-                stmt = ps;
-                this.fillStatement(ps, params);
-                rs = this.wrap(ps.executeQuery());
-            } else {
-                stmt = conn.createStatement();
-                rs = this.wrap(stmt.executeQuery(sql));
-            }
-            result = rsh.handle(rs);
-
-        } catch (final SQLException e) {
-            this.rethrow(e, sql, params);
-
-        } finally {
-            closeQuietly(rs);
-            closeQuietly(stmt);
-            if (closeConn) {
-                close(conn);
-            }
-        }
-
-        return result;
-    }
-
-    /**
-     * Execute an SQL INSERT, UPDATE, or DELETE query without replacement
-     * parameters.
-     *
-     * @param conn The connection to use to run the query.
-     * @param sql The SQL to execute.
-     * @return The number of rows updated.
-     * @throws SQLException if a database access error occurs
-     */
-    public int update(final Connection conn, final String sql) throws SQLException {
-        return this.update(conn, false, sql, (Object[]) null);
-    }
-
-    /**
-     * Execute an SQL INSERT, UPDATE, or DELETE query with a single replacement
-     * parameter.
-     *
-     * @param conn The connection to use to run the query.
-     * @param sql The SQL to execute.
-     * @param param The replacement parameter.
-     * @return The number of rows updated.
-     * @throws SQLException if a database access error occurs
-     */
-    public int update(final Connection conn, final String sql, final Object param) throws SQLException {
-        return this.update(conn, false, sql, param);
-    }
-
-    /**
-     * Execute an SQL INSERT, UPDATE, or DELETE query.
-     *
-     * @param conn The connection to use to run the query.
-     * @param sql The SQL to execute.
-     * @param params The query replacement parameters.
-     * @return The number of rows updated.
-     * @throws SQLException if a database access error occurs
-     */
-    public int update(final Connection conn, final String sql, final Object... params) throws SQLException {
-        return update(conn, false, sql, params);
-    }
-
-    /**
-     * Executes the given INSERT, UPDATE, or DELETE SQL statement without
-     * any replacement parameters. The {@code Connection} is retrieved
-     * from the {@code DataSource} set in the constructor.  This
-     * {@code Connection} must be in auto-commit mode or the update will
-     * not be saved.
-     *
-     * @param sql The SQL statement to execute.
-     * @throws SQLException if a database access error occurs
-     * @return The number of rows updated.
-     */
-    public int update(final String sql) throws SQLException {
-        final Connection conn = this.prepareConnection();
-
-        return this.update(conn, true, sql, (Object[]) null);
-    }
-
-    /**
-     * Executes the given INSERT, UPDATE, or DELETE SQL statement with
-     * a single replacement parameter.  The {@code Connection} is
-     * retrieved from the {@code DataSource} set in the constructor.
-     * This {@code Connection} must be in auto-commit mode or the
-     * update will not be saved.
-     *
-     * @param sql The SQL statement to execute.
-     * @param param The replacement parameter.
-     * @throws SQLException if a database access error occurs
-     * @return The number of rows updated.
-     */
-    public int update(final String sql, final Object param) throws SQLException {
-        final Connection conn = this.prepareConnection();
-
-        return this.update(conn, true, sql, param);
-    }
-
-    /**
-     * Executes the given INSERT, UPDATE, or DELETE SQL statement.  The
-     * {@code Connection} is retrieved from the {@code DataSource}
-     * set in the constructor.  This {@code Connection} must be in
-     * auto-commit mode or the update will not be saved.
-     *
-     * @param sql The SQL statement to execute.
-     * @param params Initializes the PreparedStatement's IN (i.e. '?')
-     * parameters.
-     * @throws SQLException if a database access error occurs
-     * @return The number of rows updated.
-     */
-    public int update(final String sql, final Object... params) throws SQLException {
-        final Connection conn = this.prepareConnection();
-
-        return this.update(conn, true, sql, params);
-    }
-
-    /**
-     * Calls update after checking the parameters to ensure nothing is null.
-     * @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 The number of rows updated.
-     * @throws SQLException If there are database or parameter errors.
-     */
-    private int update(final Connection conn, final boolean closeConn, final String sql, final Object... params) throws SQLException {
-        if (conn == null) {
-            throw new SQLException("Null connection");
-        }
-
-        if (sql == null) {
-            if (closeConn) {
-                close(conn);
-            }
-            throw new SQLException("Null SQL statement");
-        }
-
-        Statement stmt = null;
-        int rows = 0;
-
-        try {
-            if (params != null && params.length > 0) {
-                final PreparedStatement ps = this.prepareStatement(conn, sql);
-                stmt = ps;
-                this.fillStatement(ps, params);
-                rows = ps.executeUpdate();
-            } else {
-                stmt = conn.createStatement();
-                rows = stmt.executeUpdate(sql);
-            }
-
-        } catch (final SQLException e) {
-            this.rethrow(e, sql, params);
-
-        } finally {
-            close(stmt);
-            if (closeConn) {
-                close(conn);
-            }
-        }
-
-        return rows;
-    }
-
-    /**
-     * Executes the given INSERT SQL without any replacement parameters.
-     * The {@code Connection} is retrieved from the
-     * {@code DataSource} set in the constructor.
-     * @param <T> The type of object that the handler returns
-     * @param sql The SQL statement to execute.
-     * @param rsh The handler used to create the result object from
-     * the {@code ResultSet} of auto-generated keys.
-     * @return An object generated by the handler.
-     * @throws SQLException if a database access error occurs
-     * @since 1.6
-     */
-    public <T> T insert(final String sql, final ResultSetHandler<T> rsh) throws SQLException {
-        return insert(this.prepareConnection(), true, sql, rsh, (Object[]) null);
-    }
-
-    /**
-     * Executes the given INSERT SQL statement. The
-     * {@code Connection} is retrieved from the {@code DataSource}
-     * set in the constructor.  This {@code Connection} must be in
-     * auto-commit mode or the insert will not be saved.
-     * @param <T> The type of object that the handler returns
-     * @param sql The SQL statement to execute.
-     * @param rsh The handler used to create the result object from
-     * the {@code ResultSet} of auto-generated keys.
-     * @param params Initializes the PreparedStatement's IN (i.e. '?')
-     * @return An object generated by the handler.
-     * @throws SQLException if a database access error occurs
-     * @since 1.6
-     */
-    public <T> T insert(final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
-        return insert(this.prepareConnection(), true, sql, rsh, params);
-    }
-
-    /**
-     * Execute an SQL INSERT query without replacement parameters.
-     * @param <T> The type of object that the handler returns
-     * @param conn The connection to use to run the query.
-     * @param sql The SQL to execute.
-     * @param rsh The handler used to create the result object from
-     * the {@code ResultSet} of auto-generated keys.
-     * @return An object generated by the handler.
-     * @throws SQLException if a database access error occurs
-     * @since 1.6
-     */
-    public <T> T insert(final Connection conn, final String sql, final ResultSetHandler<T> rsh) throws SQLException {
-        return insert(conn, false, sql, rsh, (Object[]) null);
-    }
-
-    /**
-     * Execute an SQL INSERT query.
-     * @param <T> The type of object that the handler returns
-     * @param conn The connection to use to run the query.
-     * @param sql The SQL to execute.
-     * @param rsh The handler used to create the result object from
-     * the {@code ResultSet} of auto-generated keys.
-     * @param params The query replacement parameters.
-     * @return An object generated by the handler.
-     * @throws SQLException if a database access error occurs
-     * @since 1.6
-     */
-    public <T> T insert(final Connection conn, final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
-        return insert(conn, false, sql, rsh, params);
-    }
-
-    /**
-     * Executes the given INSERT SQL statement.
-     * @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 rsh The handler used to create the result object from
-     * the {@code ResultSet} of auto-generated keys.
-     * @param params The query replacement parameters.
-     * @return An object generated by the handler.
-     * @throws SQLException If there are database or parameter errors.
-     * @since 1.6
-     */
-    private <T> T insert(final Connection conn, final boolean closeConn, final String sql, final ResultSetHandler<T> rsh, final Object... params)
-            throws SQLException {
-        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");
-        }
-
-        Statement stmt = null;
-        T generatedKeys = null;
-
-        try {
-            if (params != null && params.length > 0) {
-                final PreparedStatement ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
-                stmt = ps;
-                this.fillStatement(ps, params);
-                ps.executeUpdate();
-            } else {
-                stmt = conn.createStatement();
-                stmt.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
-            }
-            final ResultSet resultSet = stmt.getGeneratedKeys();
-            generatedKeys = rsh.handle(resultSet);
-        } catch (final SQLException e) {
-            this.rethrow(e, sql, params);
-        } finally {
-            close(stmt);
-            if (closeConn) {
-                close(conn);
-            }
-        }
-
-        return generatedKeys;
-    }
-
-    /**
-     * Executes the given batch of INSERT SQL statements. The
-     * {@code Connection} is retrieved from the {@code DataSource}
-     * set in the constructor.  This {@code Connection} must be in
-     * auto-commit mode or the insert will not be saved.
-     * @param <T> The type of object that the handler returns
-     * @param sql The SQL statement to execute.
-     * @param rsh The handler used to create the result object from
-     * the {@code ResultSet} of auto-generated keys.
-     * @param params Initializes the PreparedStatement's IN (i.e. '?')
-     * @return The result generated by the handler.
-     * @throws SQLException if a database access error occurs
-     * @since 1.6
-     */
-    public <T> T insertBatch(final String sql, final ResultSetHandler<T> rsh, final Object[][] params) throws SQLException {
-        return insertBatch(this.prepareConnection(), true, sql, rsh, params);
-    }
-
-    /**
-     * Executes the given batch of INSERT SQL statements.
-     * @param <T> The type of object that the handler returns
-     * @param conn The connection to use to run the query.
-     * @param sql The SQL to execute.
-     * @param rsh The handler used to create the result object from
-     * the {@code ResultSet} of auto-generated keys.
-     * @param params The query replacement parameters.
-     * @return The result generated by the handler.
-     * @throws SQLException if a database access error occurs
-     * @since 1.6
-     */
-    public <T> T insertBatch(final Connection conn, final String sql, final ResultSetHandler<T> rsh, final Object[][] params) throws SQLException {
-        return insertBatch(conn, false, sql, rsh, params);
-    }
-
-    /**
-     * Executes the given batch of INSERT SQL statements.
-     * @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 rsh The handler used to create the result object from
-     * the {@code ResultSet} of auto-generated keys.
-     * @param params The query replacement parameters.
-     * @return The result generated by the handler.
-     * @throws SQLException If there are database or parameter errors.
-     * @since 1.6
-     */
-    private <T> T insertBatch(final Connection conn, final boolean closeConn, final String sql, final ResultSetHandler<T> rsh, final Object[][] params)
-            throws SQLException {
-        if (conn == null) {
-            throw new SQLException("Null connection");
-        }
-
-        if (sql == null) {
-            if (closeConn) {
-                close(conn);
-            }
-            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;
-        T generatedKeys = null;
-        try {
-            stmt = this.prepareStatement(conn, sql, Statement.RETURN_GENERATED_KEYS);
-
-            for (final Object[] param : params) {
-                this.fillStatement(stmt, param);
-                stmt.addBatch();
-            }
-            stmt.executeBatch();
-            final ResultSet rs = stmt.getGeneratedKeys();
-            generatedKeys = rsh.handle(rs);
-
-        } catch (final SQLException e) {
-            this.rethrow(e, sql, (Object[])params);
-        } finally {
-            close(stmt);
-            if (closeConn) {
-                close(conn);
-            }
-        }
-
-        return generatedKeys;
-    }
-
-    /**
-     * Execute an SQL statement, including a stored procedure call, which does
-     * not return any result sets.
-     * Any parameters which are instances of {@link OutParameter} will be
-     * registered as OUT parameters.
-     * <p>
-     * Use this method when invoking a stored procedure with OUT parameters
-     * that does not return any result sets.  If you are not invoking a stored
-     * procedure, or the stored procedure has no OUT parameters, consider using
-     * {@link #update(java.sql.Connection, java.lang.String, java.lang.Object...) }.
-     * If the stored procedure returns result sets, use
-     * {@link #execute(java.sql.Connection, java.lang.String, org.apache.commons.dbutils.ResultSetHandler, java.lang.Object...) }.
-     *
-     * @param conn The connection to use to run the query.
-     * @param sql The SQL to execute.
-     * @param params The query replacement parameters.
-     * @return The number of rows updated.
-     * @throws SQLException if a database access error occurs
-     */
-    public int execute(final Connection conn, final String sql, final Object... params) throws SQLException {
-        return this.execute(conn, false, sql, params);
-    }
-
-    /**
-     * Execute an SQL statement, including a stored procedure call, which does
-     * not return any result sets.
-     * Any parameters which are instances of {@link OutParameter} will be
-     * registered as OUT parameters.
-     * <p>
-     * Use this method when invoking a stored procedure with OUT parameters
-     * that does not return any result sets.  If you are not invoking a stored
-     * procedure, or the stored procedure has no OUT parameters, consider using
-     * {@link #update(java.lang.String, java.lang.Object...) }.
-     * If the stored procedure returns result sets, use
-     * {@link #execute(java.lang.String, org.apache.commons.dbutils.ResultSetHandler, java.lang.Object...) }.
-     * <p>
-     * The {@code Connection} is retrieved from the {@code DataSource}
-     * set in the constructor.  This {@code Connection} must be in
-     * auto-commit mode or the update will not be saved.
-     *
-     * @param sql The SQL statement to execute.
-     * @param params Initializes the CallableStatement's parameters (i.e. '?').
-     * @throws SQLException if a database access error occurs
-     * @return The number of rows updated.
-     */
-    public int execute(final String sql, final Object... params) throws SQLException {
-        final Connection conn = this.prepareConnection();
-
-        return this.execute(conn, true, sql, params);
-    }
-
-    /**
-     * Execute an SQL statement, including a stored procedure call, which
-     * returns one or more result sets.
-     * Any parameters which are instances of {@link OutParameter} will be
-     * registered as OUT parameters.
-     * <p>
-     * Use this method when: a) running SQL statements that return multiple
-     * result sets; b) invoking a stored procedure that return result
-     * sets and OUT parameters.  Otherwise you may wish to use
-     * {@link #query(java.sql.Connection, java.lang.String, org.apache.commons.dbutils.ResultSetHandler, java.lang.Object...) }
-     * (if there are no OUT parameters) or
-     * {@link #execute(java.sql.Connection, java.lang.String, java.lang.Object...) }
-     * (if there are no result sets).
-     *
-     * @param <T> The type of object that the handler returns
-     * @param conn The connection to use to run the query.
-     * @param sql The SQL to execute.
-     * @param rsh The result set handler
-     * @param params The query replacement parameters.
-     * @return A list of objects generated by the handler
-     * @throws SQLException if a database access error occurs
-     */
-    public <T> List<T> execute(final Connection conn, final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
-        return this.execute(conn, false, sql, rsh, params);
-    }
-
-    /**
-     * Execute an SQL statement, including a stored procedure call, which
-     * returns one or more result sets.
-     * Any parameters which are instances of {@link OutParameter} will be
-     * registered as OUT parameters.
-     * <p>
-     * Use this method when: a) running SQL statements that return multiple
-     * result sets; b) invoking a stored procedure that return result
-     * sets and OUT parameters.  Otherwise you may wish to use
-     * {@link #query(java.lang.String, org.apache.commons.dbutils.ResultSetHandler, java.lang.Object...) }
-     * (if there are no OUT parameters) or
-     * {@link #execute(java.lang.String, java.lang.Object...) }
-     * (if there are no result sets).
-     *
-     * @param <T> The type of object that the handler returns
-     * @param sql The SQL to execute.
-     * @param rsh The result set handler
-     * @param params The query replacement parameters.
-     * @return A list of objects generated by the handler
-     * @throws SQLException if a database access error occurs
-     */
-    public <T> List<T> execute(final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
-        final Connection conn = this.prepareConnection();
-
-        return this.execute(conn, true, sql, rsh, params);
-    }
-
-    /**
-     * Invokes the stored procedure via update after checking the parameters to
-     * ensure nothing is null.
-     * @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 The number of rows updated.
-     * @throws SQLException If there are database or parameter errors.
-     */
-    private int execute(final Connection conn, final boolean closeConn, final String sql, final Object... params) throws SQLException {
-        if (conn == null) {
-            throw new SQLException("Null connection");
-        }
-
-        if (sql == null) {
-            if (closeConn) {
-                close(conn);
-            }
-            throw new SQLException("Null SQL statement");
-        }
-
-        CallableStatement stmt = null;
-        int rows = 0;
-
-        try {
-            stmt = this.prepareCall(conn, sql);
-            this.fillStatement(stmt, params);
-            stmt.execute();
-            rows = stmt.getUpdateCount();
-            this.retrieveOutParameters(stmt, params);
-
-        } catch (final SQLException e) {
-            this.rethrow(e, sql, params);
-
-        } finally {
-            close(stmt);
-            if (closeConn) {
-                close(conn);
-            }
-        }
-
-        return rows;
-    }
-
-    /**
-     * Invokes the stored procedure via update after checking the parameters to
-     * ensure nothing is null.
-     * @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 rsh The result set handler
-     * @param params An array of update replacement parameters.  Each row in
-     * this array is one set of update replacement values.
-     * @return List of all objects generated by the ResultSetHandler for all result sets handled.
-     * @throws SQLException If there are database or parameter errors.
-     */
-    private <T> List<T> execute(final Connection conn, final boolean closeConn, final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
-        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");
-        }
-
-        CallableStatement stmt = null;
-        final List<T> results = new LinkedList<>();
-
-        try {
-            stmt = this.prepareCall(conn, sql);
-            this.fillStatement(stmt, params);
-            boolean moreResultSets = stmt.execute();
-            // Handle multiple result sets by passing them through the handler
-            // retaining the final result
-            ResultSet rs = null;
-            while (moreResultSets) {
-                try {
-                    rs = this.wrap(stmt.getResultSet());
-                    results.add(rsh.handle(rs));
-                    moreResultSets = stmt.getMoreResults();
-
-                } finally {
-                    close(rs);
-                }
-            }
-            this.retrieveOutParameters(stmt, params);
-
-        } catch (final SQLException e) {
-            this.rethrow(e, sql, params);
-
-        } finally {
-            close(stmt);
-            if (closeConn) {
-                close(conn);
-            }
-        }
-
-        return results;
-    }
-
-    /**
-     * Set the value on all the {@link OutParameter} instances in the
-     * {@code params} array using the OUT parameter values from the
-     * {@code stmt}.
-     * @param stmt the statement from which to retrieve OUT parameter values
-     * @param params the parameter array for the statement invocation
-     * @throws SQLException when the value could not be retrieved from the
-     * statement.
-     */
-    private void retrieveOutParameters(final CallableStatement stmt, final Object[] params) throws SQLException {
-        if (params != null) {
-            for (int i = 0; i < params.length; i++) {
-                if (params[i] instanceof OutParameter) {
-                    ((OutParameter)params[i]).setValue(stmt, i + 1);
-                }
-            }
-        }
-    }
-}
+/*
+ * 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.
+ */
+package org.apache.commons.dbutils;
+
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.LinkedList;
+import java.util.List;
+import javax.sql.DataSource;
+
+/**
+ * Executes SQL queries with pluggable strategies for handling
+ * {@code ResultSet}s.  This class is thread safe.
+ *
+ * @see ResultSetHandler
+ */
+public class QueryRunner extends AbstractQueryRunner {
+
+    /**
+     * Constructor for QueryRunner.
+     */
+    public QueryRunner() {
+    }
+
+    /**
+     * Constructor for QueryRunner that controls the use of {@code ParameterMetaData}.
+     *
+     * @param pmdKnownBroken Some drivers don't support {@link java.sql.ParameterMetaData#getParameterType(int) };
+     * if {@code pmdKnownBroken} 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 QueryRunner(final boolean pmdKnownBroken) {
+        super(pmdKnownBroken);
+    }
+
+    /**
+     * Constructor for QueryRunner that takes a {@code DataSource} to use.
+     *
+     * Methods that do not take a {@code Connection} parameter will retrieve connections from this
+     * {@code DataSource}.
+     *
+     * @param ds The {@code DataSource} to retrieve connections from.
+     */
+    public QueryRunner(final DataSource ds) {
+        super(ds);
+    }
+
+    /**
+     * Constructor for QueryRunner that takes a {@code StatementConfiguration} to configure statements when
+     * preparing them.
+     *
+     * @param stmtConfig The configuration to apply to statements when they are prepared.
+     */
+    public QueryRunner(final StatementConfiguration stmtConfig) {
+        super(stmtConfig);
+    }
+
+    /**
+     * Constructor for QueryRunner that takes a {@code DataSource} and controls the use of {@code ParameterMetaData}.
+     * Methods that do not take a {@code Connection} parameter will retrieve connections from this
+     * {@code DataSource}.
+     *
+     * @param ds The {@code DataSource} to retrieve connections from.
+     * @param pmdKnownBroken Some drivers don't support {@link java.sql.ParameterMetaData#getParameterType(int) };
+     * if {@code pmdKnownBroken} 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 QueryRunner(final DataSource ds, final boolean pmdKnownBroken) {
+        super(ds, pmdKnownBroken);
+    }
+
+    /**
+     * Constructor for QueryRunner that takes a {@code DataSource} to use and a {@code StatementConfiguration}.
+     *
+     * Methods that do not take a {@code Connection} parameter will retrieve connections from this
+     * {@code DataSource}.
+     *
+     * @param ds The {@code DataSource} to retrieve connections from.
+     * @param stmtConfig The configuration to apply to statements when they are prepared.
+     */
+    public QueryRunner(final DataSource ds, final StatementConfiguration stmtConfig) {
+        super(ds, stmtConfig);
+    }
+
+    /**
+     * Constructor for QueryRunner that takes a {@code DataSource}, a {@code StatementConfiguration}, and
+     * controls the use of {@code ParameterMetaData}.  Methods that do not take a {@code Connection} parameter
+     * will retrieve connections from this {@code DataSource}.
+     *
+     * @param ds The {@code DataSource} to retrieve connections from.
+     * @param pmdKnownBroken Some drivers don't support {@link java.sql.ParameterMetaData#getParameterType(int) };
+     * if {@code pmdKnownBroken} 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 stmtConfig The configuration to apply to statements when they are prepared.
+     */
+    public QueryRunner(final DataSource ds, final boolean pmdKnownBroken, final StatementConfiguration stmtConfig) {
+        super(ds, pmdKnownBroken, stmtConfig);
+    }
+
+    /**
+     * Execute a batch of SQL INSERT, UPDATE, or DELETE queries.
+     *
+     * @param conn The Connection to use to run the query.  The caller is
+     * responsible for closing this Connection.
+     * @param sql The SQL to execute.
+     * @param params An array of query replacement parameters.  Each row in
+     * this array is one set of batch replacement values.
+     * @return The number of rows updated per statement.
+     * @throws SQLException if a database access error occurs
+     * @since DbUtils 1.1
+     */
+    public int[] batch(final Connection conn, final String sql, final Object[][] params) throws SQLException {
+        return this.batch(conn, false, sql, params);
+    }
+
+    /**
+     * Execute a batch of SQL INSERT, UPDATE, or DELETE queries.  The
+     * {@code Connection} is retrieved from the {@code DataSource}
+     * set in the constructor.  This {@code Connection} must be in
+     * auto-commit mode or the update will not be saved.
+     *
+     * @param sql The SQL to execute.
+     * @param params An array of query replacement parameters.  Each row in
+     * this array is one set of batch replacement values.
+     * @return The number of rows updated per statement.
+     * @throws SQLException if a database access error occurs
+     * @since DbUtils 1.1
+     */
+    public int[] batch(final String sql, final Object[][] params) throws SQLException {
+        final Connection conn = this.prepareConnection();
+
+        return this.batch(conn, true, sql, params);
+    }
+
+    /**
+     * Calls update after checking the parameters to ensure nothing is null.
+     * @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 The number of rows updated in the batch.
+     * @throws SQLException If there are database or parameter errors.
+     */
+    private int[] batch(final Connection conn, final boolean closeConn, final String sql, final Object[][] params) throws SQLException {
+        if (conn == null) {
+            throw new SQLException("Null connection");
+        }
+
+        if (sql == null) {
+            if (closeConn) {
+                close(conn);
+            }
+            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;
+        int[] rows = null;
+        try {
+            stmt = this.prepareStatement(conn, sql);
+
+            for (final Object[] param : params) {
+                this.fillStatement(stmt, param);
+                stmt.addBatch();
+            }
+            rows = stmt.executeBatch();
+
+        } catch (final SQLException e) {
+            this.rethrow(e, sql, (Object[])params);
+        } finally {
+            close(stmt);
+            if (closeConn) {
+                close(conn);
+            }
+        }
+
+        return rows;
+    }
+
+    /**
+     * Execute an SQL SELECT query with a single replacement parameter. The
+     * caller is responsible for closing the connection.
+     * @param <T> The type of object that the handler returns
+     * @param conn The connection to execute the query in.
+     * @param sql The query to execute.
+     * @param param The replacement parameter.
+     * @param rsh The handler that converts the results into an object.
+     * @return The object returned by the handler.
+     * @throws SQLException if a database access error occurs
+     * @deprecated Use {@link #query(Connection, String, ResultSetHandler, Object...)}
+     */
+    @Deprecated
+    public <T> T query(final Connection conn, final String sql, final Object param, final ResultSetHandler<T> rsh) throws SQLException {
+        return this.<T>query(conn, false, sql, rsh, param);
+    }
+
+    /**
+     * 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
+     * @param conn The connection to execute the query in.
+     * @param sql The query to execute.
+     * @param params The replacement parameters.
+     * @param rsh The handler that converts the results into an object.
+     * @return The object returned by the handler.
+     * @throws SQLException if a database access error occurs
+     * @deprecated Use {@link #query(Connection,String,ResultSetHandler,Object...)} instead
+     */
+    @Deprecated
+    public <T> T query(final Connection conn, final String sql, final Object[] params, final ResultSetHandler<T> rsh) throws SQLException {
+        return this.<T>query(conn, false, sql, rsh, params);
+    }
+
+    /**
+     * 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
+     * @param conn The connection to execute the query in.
+     * @param sql The query to execute.
+     * @param rsh The handler that converts the results into an object.
+     * @param params The replacement parameters.
+     * @return The object returned by the handler.
+     * @throws SQLException if a database access error occurs
+     */
+    public <T> T query(final Connection conn, final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
+        return this.<T>query(conn, false, sql, rsh, params);
+    }
+
+    /**
+     * Execute an SQL SELECT query without any replacement parameters.  The
+     * caller is responsible for closing the connection.
+     * @param <T> The type of object that the handler returns
+     * @param conn The connection to execute the query in.
+     * @param sql The query to execute.
+     * @param rsh The handler that converts the results into an object.
+     * @return The object returned by the handler.
+     * @throws SQLException if a database access error occurs
+     */
+    public <T> T query(final Connection conn, final String sql, final ResultSetHandler<T> rsh) throws SQLException {
+        return this.<T>query(conn, false, sql, rsh, (Object[]) null);
+    }
+
+    /**
+     * Executes the given SELECT SQL with a single replacement parameter.
+     * The {@code Connection} is retrieved from the
+     * {@code DataSource} set in the constructor.
+     * @param <T> The type of object that the handler returns
+     * @param sql The SQL statement to execute.
+     * @param param The replacement parameter.
+     * @param rsh The handler used to create the result object from
+     * the {@code ResultSet}.
+     *
+     * @return An object generated by the handler.
+     * @throws SQLException if a database access error occurs
+     * @deprecated Use {@link #query(String, ResultSetHandler, Object...)}
+     */
+    @Deprecated
+    public <T> T query(final String sql, final Object param, final ResultSetHandler<T> rsh) throws SQLException {
+        final Connection conn = this.prepareConnection();
+
+        return this.<T>query(conn, true, sql, rsh, param);
+    }
+
+    /**
+     * Executes the given SELECT SQL query and returns a result object.
+     * The {@code Connection} is retrieved from the
+     * {@code DataSource} set in the constructor.
+     * @param <T> The type of object that the handler returns
+     * @param sql The SQL statement to execute.
+     * @param params Initialize the PreparedStatement's IN parameters with
+     * this array.
+     *
+     * @param rsh The handler used to create the result object from
+     * the {@code ResultSet}.
+     *
+     * @return An object generated by the handler.
+     * @throws SQLException if a database access error occurs
+     * @deprecated Use {@link #query(String, ResultSetHandler, Object...)}
+     */
+    @Deprecated
+    public <T> T query(final String sql, final Object[] params, final ResultSetHandler<T> rsh) throws SQLException {
+        final Connection conn = this.prepareConnection();
+
+        return this.<T>query(conn, true, sql, rsh, params);
+    }
+
+    /**
+     * Executes the given SELECT SQL query and returns a result object.
+     * The {@code Connection} is retrieved from the
+     * {@code DataSource} set in the constructor.
+     * @param <T> The type of object that the handler returns
+     * @param sql The SQL statement to execute.
+     * @param rsh The handler used to create the result object from
+     * the {@code ResultSet}.
+     * @param params Initialize the PreparedStatement's IN parameters with
+     * this array.
+     * @return An object generated by the handler.
+     * @throws SQLException if a database access error occurs
+     */
+    public <T> T query(final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
+        final Connection conn = this.prepareConnection();
+
+        return this.<T>query(conn, true, sql, rsh, params);
+    }
+
+    /**
+     * Executes the given SELECT SQL without any replacement parameters.
+     * The {@code Connection} is retrieved from the
+     * {@code DataSource} set in the constructor.
+     * @param <T> The type of object that the handler returns
+     * @param sql The SQL statement to execute.
+     * @param rsh The handler used to create the result object from
+     * the {@code ResultSet}.
+     *
+     * @return An object generated by the handler.
+     * @throws SQLException if a database access error occurs
+     */
+    public <T> T query(final String sql, final ResultSetHandler<T> rsh) throws SQLException {
+        final Connection conn = this.prepareConnection();
+
+        return this.<T>query(conn, true, sql, rsh, (Object[]) null);
+    }
+
+    /**
+     * Calls query after checking the parameters to ensure nothing is null.
+     * @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 batch replacement values.
+     * @return The results of the query.
+     * @throws SQLException If there are database or parameter errors.
+     */
+    private <T> T query(final Connection conn, final boolean closeConn, final String sql, final ResultSetHandler<T> rsh, final Object... params)
+            throws SQLException {
+        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");
+        }
+
+        Statement stmt = null;
+        ResultSet rs = null;
+        T result = null;
+
+        try {
+            if (params != null && params.length > 0) {
+                final PreparedStatement ps = this.prepareStatement(conn, sql);
+                stmt = ps;
+                this.fillStatement(ps, params);
+                rs = this.wrap(ps.executeQuery());
+            } else {
+                stmt = conn.createStatement();
+                rs = this.wrap(stmt.executeQuery(sql));
+            }
+            result = rsh.handle(rs);
+
+        } catch (final SQLException e) {
+            this.rethrow(e, sql, params);
+
+        } finally {
+            closeQuietly(rs);
+            closeQuietly(stmt);
+            if (closeConn) {
+                close(conn);
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Execute an SQL INSERT, UPDATE, or DELETE query without replacement
+     * parameters.
+     *
+     * @param conn The connection to use to run the query.
+     * @param sql The SQL to execute.
+     * @return The number of rows updated.
+     * @throws SQLException if a database access error occurs
+     */
+    public int update(final Connection conn, final String sql) throws SQLException {
+        return this.update(conn, false, sql, (Object[]) null);
+    }
+
+    /**
+     * Execute an SQL INSERT, UPDATE, or DELETE query with a single replacement
+     * parameter.
+     *
+     * @param conn The connection to use to run the query.
+     * @param sql The SQL to execute.
+     * @param param The replacement parameter.
+     * @return The number of rows updated.
+     * @throws SQLException if a database access error occurs
+     */
+    public int update(final Connection conn, final String sql, final Object param) throws SQLException {
+        return this.update(conn, false, sql, param);
+    }
+
+    /**
+     * Execute an SQL INSERT, UPDATE, or DELETE query.
+     *
+     * @param conn The connection to use to run the query.
+     * @param sql The SQL to execute.
+     * @param params The query replacement parameters.
+     * @return The number of rows updated.
+     * @throws SQLException if a database access error occurs
+     */
+    public int update(final Connection conn, final String sql, final Object... params) throws SQLException {
+        return update(conn, false, sql, params);
+    }
+
+    /**
+     * Executes the given INSERT, UPDATE, or DELETE SQL statement without
+     * any replacement parameters. The {@code Connection} is retrieved
+     * from the {@code DataSource} set in the constructor.  This
+     * {@code Connection} must be in auto-commit mode or the update will
+     * not be saved.
+     *
+     * @param sql The SQL statement to execute.
+     * @throws SQLException if a database access error occurs
+     * @return The number of rows updated.
+     */
+    public int update(final String sql) throws SQLException {
+        final Connection conn = this.prepareConnection();
+
+        return this.update(conn, true, sql, (Object[]) null);
+    }
+
+    /**
+     * Executes the given INSERT, UPDATE, or DELETE SQL statement with
+     * a single replacement parameter.  The {@code Connection} is
+     * retrieved from the {@code DataSource} set in the constructor.
+     * This {@code Connection} must be in auto-commit mode or the
+     * update will not be saved.
+     *
+     * @param sql The SQL statement to execute.
+     * @param param The replacement parameter.
+     * @throws SQLException if a database access error occurs
+     * @return The number of rows updated.
+     */
+    public int update(final String sql, final Object param) throws SQLException {
+        final Connection conn = this.prepareConnection();
+
+        return this.update(conn, true, sql, param);
+    }
+
+    /**
+     * Executes the given INSERT, UPDATE, or DELETE SQL statement.  The
+     * {@code Connection} is retrieved from the {@code DataSource}
+     * set in the constructor.  This {@code Connection} must be in
+     * auto-commit mode or the update will not be saved.
+     *
+     * @param sql The SQL statement to execute.
+     * @param params Initializes the PreparedStatement's IN (i.e. '?')
+     * parameters.
+     * @throws SQLException if a database access error occurs
+     * @return The number of rows updated.
+     */
+    public int update(final String sql, final Object... params) throws SQLException {
+        final Connection conn = this.prepareConnection();
+
+        return this.update(conn, true, sql, params);
+    }
+
+    /**
+     * Calls update after checking the parameters to ensure nothing is null.
+     * @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 The number of rows updated.
+     * @throws SQLException If there are database or parameter errors.
+     */
+    private int update(final Connection conn, final boolean closeConn, final String sql, final Object... params) throws SQLException {
+        if (conn == null) {
+            throw new SQLException("Null connection");
+        }
+
+        if (sql == null) {
+            if (closeConn) {
+                close(conn);
+            }
+            throw new SQLException("Null SQL statement");
+        }
+
+        Statement stmt = null;
+        int rows = 0;
+
+        try {
+            if (params != null && params.length > 0) {
+                final PreparedStatement ps = this.prepareStatement(conn, sql);
+                stmt = ps;
+                this.fillStatement(ps, params);
+                rows = ps.executeUpdate();
+            } else {
+                stmt = conn.createStatement();
+                rows = stmt.executeUpdate(sql);
+            }
+
+        } catch (final SQLException e) {
+            this.rethrow(e, sql, params);
+
+        } finally {
+            close(stmt);
+            if (closeConn) {
+                close(conn);
+            }
+        }
+
+        return rows;
+    }
+
+    /**
+     * Executes the given INSERT SQL without any replacement parameters.
+     * The {@code Connection} is retrieved from the
+     * {@code DataSource} set in the constructor.
+     * @param <T> The type of object that the handler returns
+     * @param sql The SQL statement to execute.
+     * @param rsh The handler used to create the result object from
+     * the {@code ResultSet} of auto-generated keys.
+     * @return An object generated by the handler.
+     * @throws SQLException if a database access error occurs
+     * @since 1.6
+     */
+    public <T> T insert(final String sql, final ResultSetHandler<T> rsh) throws SQLException {
+        return insert(this.prepareConnection(), true, sql, rsh, (Object[]) null);
+    }
+
+    /**
+     * Executes the given INSERT SQL statement. The
+     * {@code Connection} is retrieved from the {@code DataSource}
+     * set in the constructor.  This {@code Connection} must be in
+     * auto-commit mode or the insert will not be saved.
+     * @param <T> The type of object that the handler returns
+     * @param sql The SQL statement to execute.
+     * @param rsh The handler used to create the result object from
+     * the {@code ResultSet} of auto-generated keys.
+     * @param params Initializes the PreparedStatement's IN (i.e. '?')
+     * @return An object generated by the handler.
+     * @throws SQLException if a database access error occurs
+     * @since 1.6
+     */
+    public <T> T insert(final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
+        return insert(this.prepareConnection(), true, sql, rsh, params);
+    }
+
+    /**
+     * Execute an SQL INSERT query without replacement parameters.
+     * @param <T> The type of object that the handler returns
+     * @param conn The connection to use to run the query.
+     * @param sql The SQL to execute.
+     * @param rsh The handler used to create the result object from
+     * the {@code ResultSet} of auto-generated keys.
+     * @return An object generated by the handler.
+     * @throws SQLException if a database access error occurs
+     * @since 1.6
+     */
+    public <T> T insert(final Connection conn, final String sql, final ResultSetHandler<T> rsh) throws SQLException {
+        return insert(conn, false, sql, rsh, (Object[]) null);
+    }
+
+    /**
+     * Execute an SQL INSERT query.
+     * @param <T> The type of object that the handler returns
+     * @param conn The connection to use to run the query.
+     * @param sql The SQL to execute.
+     * @param rsh The handler used to create the result object from
+     * the {@code ResultSet} of auto-generated keys.
+     * @param params The query replacement parameters.
+     * @return An object generated by the handler.
+     * @throws SQLException if a database access error occurs
+     * @since 1.6
+     */
+    public <T> T insert(final Connection conn, final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
+        return insert(conn, false, sql, rsh, params);
+    }
+
+    /**
+     * Executes the given INSERT SQL statement.
+     * @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 rsh The handler used to create the result object from
+     * the {@code ResultSet} of auto-generated keys.
+     * @param params The query replacement parameters.
+     * @return An object generated by the handler.
+     * @throws SQLException If there are database or parameter errors.
+     * @since 1.6
+     */
+    private <T> T insert(final Connection conn, final boolean closeConn, final String sql, final ResultSetHandler<T> rsh, final Object... params)
+            throws SQLException {
+        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");
+        }
+
+        Statement stmt = null;
+        T generatedKeys = null;
+
+        try {
+            if (params != null && params.length > 0) {
+                final PreparedStatement ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
+                stmt = ps;
+                this.fillStatement(ps, params);
+                ps.executeUpdate();
+            } else {
+                stmt = conn.createStatement();
+                stmt.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
+            }
+            final ResultSet resultSet = stmt.getGeneratedKeys();
+            generatedKeys = rsh.handle(resultSet);
+        } catch (final SQLException e) {
+            this.rethrow(e, sql, params);
+        } finally {
+            close(stmt);
+            if (closeConn) {
+                close(conn);
+            }
+        }
+
+        return generatedKeys;
+    }
+
+    /**
+     * Executes the given batch of INSERT SQL statements. The
+     * {@code Connection} is retrieved from the {@code DataSource}
+     * set in the constructor.  This {@code Connection} must be in
+     * auto-commit mode or the insert will not be saved.
+     * @param <T> The type of object that the handler returns
+     * @param sql The SQL statement to execute.
+     * @param rsh The handler used to create the result object from
+     * the {@code ResultSet} of auto-generated keys.
+     * @param params Initializes the PreparedStatement's IN (i.e. '?')
+     * @return The result generated by the handler.
+     * @throws SQLException if a database access error occurs
+     * @since 1.6
+     */
+    public <T> T insertBatch(final String sql, final ResultSetHandler<T> rsh, final Object[][] params) throws SQLException {
+        return insertBatch(this.prepareConnection(), true, sql, rsh, params);
+    }
+
+    /**
+     * Executes the given batch of INSERT SQL statements.
+     * @param <T> The type of object that the handler returns
+     * @param conn The connection to use to run the query.
+     * @param sql The SQL to execute.
+     * @param rsh The handler used to create the result object from
+     * the {@code ResultSet} of auto-generated keys.
+     * @param params The query replacement parameters.
+     * @return The result generated by the handler.
+     * @throws SQLException if a database access error occurs
+     * @since 1.6
+     */
+    public <T> T insertBatch(final Connection conn, final String sql, final ResultSetHandler<T> rsh, final Object[][] params) throws SQLException {
+        return insertBatch(conn, false, sql, rsh, params);
+    }
+
+    /**
+     * Executes the given batch of INSERT SQL statements.
+     * @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 rsh The handler used to create the result object from
+     * the {@code ResultSet} of auto-generated keys.
+     * @param params The query replacement parameters.
+     * @return The result generated by the handler.
+     * @throws SQLException If there are database or parameter errors.
+     * @since 1.6
+     */
+    private <T> T insertBatch(final Connection conn, final boolean closeConn, final String sql, final ResultSetHandler<T> rsh, final Object[][] params)
+            throws SQLException {
+        if (conn == null) {
+            throw new SQLException("Null connection");
+        }
+
+        if (sql == null) {
+            if (closeConn) {
+                close(conn);
+            }
+            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;
+        T generatedKeys = null;
+        try {
+            stmt = this.prepareStatement(conn, sql, Statement.RETURN_GENERATED_KEYS);
+
+            for (final Object[] param : params) {
+                this.fillStatement(stmt, param);
+                stmt.addBatch();
+            }
+            stmt.executeBatch();
+            final ResultSet rs = stmt.getGeneratedKeys();
+            generatedKeys = rsh.handle(rs);
+
+        } catch (final SQLException e) {
+            this.rethrow(e, sql, (Object[])params);
+        } finally {
+            close(stmt);
+            if (closeConn) {
+                close(conn);
+            }
+        }
+
+        return generatedKeys;
+    }
+
+    /**
+     * Execute an SQL statement, including a stored procedure call, which does
+     * not return any result sets.
+     * Any parameters which are instances of {@link OutParameter} will be
+     * registered as OUT parameters.
+     * <p>
+     * Use this method when invoking a stored procedure with OUT parameters
+     * that does not return any result sets.  If you are not invoking a stored
+     * procedure, or the stored procedure has no OUT parameters, consider using
+     * {@link #update(java.sql.Connection, String, Object...) }.
+     * If the stored procedure returns result sets, use
+     * {@link #execute(java.sql.Connection, String, org.apache.commons.dbutils.ResultSetHandler, Object...) }.
+     *
+     * @param conn The connection to use to run the query.
+     * @param sql The SQL to execute.
+     * @param params The query replacement parameters.
+     * @return The number of rows updated.
+     * @throws SQLException if a database access error occurs
+     */
+    public int execute(final Connection conn, final String sql, final Object... params) throws SQLException {
+        return this.execute(conn, false, sql, params);
+    }
+
+    /**
+     * Execute an SQL statement, including a stored procedure call, which does
+     * not return any result sets.
+     * Any parameters which are instances of {@link OutParameter} will be
+     * registered as OUT parameters.
+     * <p>
+     * Use this method when invoking a stored procedure with OUT parameters
+     * that does not return any result sets.  If you are not invoking a stored
+     * procedure, or the stored procedure has no OUT parameters, consider using
+     * {@link #update(String, Object...) }.
+     * If the stored procedure returns result sets, use
+     * {@link #execute(String, org.apache.commons.dbutils.ResultSetHandler, Object...) }.
+     * <p>
+     * The {@code Connection} is retrieved from the {@code DataSource}
+     * set in the constructor.  This {@code Connection} must be in
+     * auto-commit mode or the update will not be saved.
+     *
+     * @param sql The SQL statement to execute.
+     * @param params Initializes the CallableStatement's parameters (i.e. '?').
+     * @throws SQLException if a database access error occurs
+     * @return The number of rows updated.
+     */
+    public int execute(final String sql, final Object... params) throws SQLException {
+        final Connection conn = this.prepareConnection();
+
+        return this.execute(conn, true, sql, params);
+    }
+
+    /**
+     * Execute an SQL statement, including a stored procedure call, which
+     * returns one or more result sets.
+     * Any parameters which are instances of {@link OutParameter} will be
+     * registered as OUT parameters.
+     * <p>
+     * Use this method when: a) running SQL statements that return multiple
+     * result sets; b) invoking a stored procedure that return result
+     * sets and OUT parameters.  Otherwise you may wish to use
+     * {@link #query(java.sql.Connection, String, org.apache.commons.dbutils.ResultSetHandler, Object...) }
+     * (if there are no OUT parameters) or
+     * {@link #execute(java.sql.Connection, String, Object...) }
+     * (if there are no result sets).
+     *
+     * @param <T> The type of object that the handler returns
+     * @param conn The connection to use to run the query.
+     * @param sql The SQL to execute.
+     * @param rsh The result set handler
+     * @param params The query replacement parameters.
+     * @return A list of objects generated by the handler
+     * @throws SQLException if a database access error occurs
+     */
+    public <T> List<T> execute(final Connection conn, final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
+        return this.execute(conn, false, sql, rsh, params);
+    }
+
+    /**
+     * Execute an SQL statement, including a stored procedure call, which
+     * returns one or more result sets.
+     * Any parameters which are instances of {@link OutParameter} will be
+     * registered as OUT parameters.
+     * <p>
+     * Use this method when: a) running SQL statements that return multiple
+     * result sets; b) invoking a stored procedure that return result
+     * sets and OUT parameters.  Otherwise you may wish to use
+     * {@link #query(String, org.apache.commons.dbutils.ResultSetHandler, Object...) }
+     * (if there are no OUT parameters) or
+     * {@link #execute(String, Object...) }
+     * (if there are no result sets).
+     *
+     * @param <T> The type of object that the handler returns
+     * @param sql The SQL to execute.
+     * @param rsh The result set handler
+     * @param params The query replacement parameters.
+     * @return A list of objects generated by the handler
+     * @throws SQLException if a database access error occurs
+     */
+    public <T> List<T> execute(final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
+        final Connection conn = this.prepareConnection();
+
+        return this.execute(conn, true, sql, rsh, params);
+    }
+
+    /**
+     * Invokes the stored procedure via update after checking the parameters to
+     * ensure nothing is null.
+     * @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 The number of rows updated.
+     * @throws SQLException If there are database or parameter errors.
+     */
+    private int execute(final Connection conn, final boolean closeConn, final String sql, final Object... params) throws SQLException {
+        if (conn == null) {
+            throw new SQLException("Null connection");
+        }
+
+        if (sql == null) {
+            if (closeConn) {
+                close(conn);
+            }
+            throw new SQLException("Null SQL statement");
+        }
+
+        CallableStatement stmt = null;
+        int rows = 0;
+
+        try {
+            stmt = this.prepareCall(conn, sql);
+            this.fillStatement(stmt, params);
+            stmt.execute();
+            rows = stmt.getUpdateCount();
+            this.retrieveOutParameters(stmt, params);
+
+        } catch (final SQLException e) {
+            this.rethrow(e, sql, params);
+
+        } finally {
+            close(stmt);
+            if (closeConn) {
+                close(conn);
+            }
+        }
+
+        return rows;
+    }
+
+    /**
+     * Invokes the stored procedure via update after checking the parameters to
+     * ensure nothing is null.
+     * @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 rsh The result set handler
+     * @param params An array of update replacement parameters.  Each row in
+     * this array is one set of update replacement values.
+     * @return List of all objects generated by the ResultSetHandler for all result sets handled.
+     * @throws SQLException If there are database or parameter errors.
+     */
+    private <T> List<T> execute(final Connection conn, final boolean closeConn, final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
+        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");
+        }
+
+        CallableStatement stmt = null;
+        final List<T> results = new LinkedList<>();
+
+        try {
+            stmt = this.prepareCall(conn, sql);
+            this.fillStatement(stmt, params);
+            boolean moreResultSets = stmt.execute();
+            // Handle multiple result sets by passing them through the handler
+            // retaining the final result
+            ResultSet rs = null;
+            while (moreResultSets) {
+                try {
+                    rs = this.wrap(stmt.getResultSet());
+                    results.add(rsh.handle(rs));
+                    moreResultSets = stmt.getMoreResults();
+
+                } finally {
+                    close(rs);
+                }
+            }
+            this.retrieveOutParameters(stmt, params);
+
+        } catch (final SQLException e) {
+            this.rethrow(e, sql, params);
+
+        } finally {
+            close(stmt);
+            if (closeConn) {
+                close(conn);
+            }
+        }
+
+        return results;
+    }
+
+    /**
+     * Set the value on all the {@link OutParameter} instances in the
+     * {@code params} array using the OUT parameter values from the
+     * {@code stmt}.
+     * @param stmt the statement from which to retrieve OUT parameter values
+     * @param params the parameter array for the statement invocation
+     * @throws SQLException when the value could not be retrieved from the
+     * statement.
+     */
+    private void retrieveOutParameters(final CallableStatement stmt, final Object[] params) throws SQLException {
+        if (params != null) {
+            for (int i = 0; i < params.length; i++) {
+                if (params[i] instanceof OutParameter) {
+                    ((OutParameter)params[i]).setValue(stmt, i + 1);
+                }
+            }
+        }
+    }
+}