QueryRunner.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.dbutils;

  18. import java.sql.CallableStatement;
  19. import java.sql.Connection;
  20. import java.sql.ParameterMetaData;
  21. import java.sql.PreparedStatement;
  22. import java.sql.ResultSet;
  23. import java.sql.SQLException;
  24. import java.sql.Statement;
  25. import java.util.LinkedList;
  26. import java.util.List;

  27. import javax.sql.DataSource;

  28. /**
  29.  * Executes SQL queries with pluggable strategies for handling
  30.  * {@code ResultSet}s.  This class is thread safe.
  31.  *
  32.  * @see ResultSetHandler
  33.  */
  34. public class QueryRunner extends AbstractQueryRunner {

  35.     /**
  36.      * Constructor for QueryRunner.
  37.      */
  38.     public QueryRunner() {
  39.     }

  40.     /**
  41.      * Constructor for QueryRunner that controls the use of {@code ParameterMetaData}.
  42.      *
  43.      * @param pmdKnownBroken Some drivers don't support {@link java.sql.ParameterMetaData#getParameterType(int) };
  44.      * if {@code pmdKnownBroken} is set to true, we won't even try it; if false, we'll try it,
  45.      * and if it breaks, we'll remember not to use it again.
  46.      */
  47.     public QueryRunner(final boolean pmdKnownBroken) {
  48.         super(pmdKnownBroken);
  49.     }

  50.     /**
  51.      * Constructor for QueryRunner that takes a {@code DataSource} to use.
  52.      *
  53.      * Methods that do not take a {@code Connection} parameter will retrieve connections from this
  54.      * {@code DataSource}.
  55.      *
  56.      * @param ds The {@code DataSource} to retrieve connections from.
  57.      */
  58.     public QueryRunner(final DataSource ds) {
  59.         super(ds);
  60.     }

  61.     /**
  62.      * Constructor for QueryRunner that takes a {@code DataSource} and controls the use of {@code ParameterMetaData}.
  63.      * Methods that do not take a {@code Connection} parameter will retrieve connections from this
  64.      * {@code DataSource}.
  65.      *
  66.      * @param ds The {@code DataSource} to retrieve connections from.
  67.      * @param pmdKnownBroken Some drivers don't support {@link java.sql.ParameterMetaData#getParameterType(int) };
  68.      * if {@code pmdKnownBroken} is set to true, we won't even try it; if false, we'll try it,
  69.      * and if it breaks, we'll remember not to use it again.
  70.      */
  71.     public QueryRunner(final DataSource ds, final boolean pmdKnownBroken) {
  72.         super(ds, pmdKnownBroken);
  73.     }

  74.     /**
  75.      * Constructor for QueryRunner that takes a {@code DataSource}, a {@code StatementConfiguration}, and
  76.      * controls the use of {@code ParameterMetaData}.  Methods that do not take a {@code Connection} parameter
  77.      * will retrieve connections from this {@code DataSource}.
  78.      *
  79.      * @param ds The {@code DataSource} to retrieve connections from.
  80.      * @param pmdKnownBroken Some drivers don't support {@link java.sql.ParameterMetaData#getParameterType(int) };
  81.      * if {@code pmdKnownBroken} is set to true, we won't even try it; if false, we'll try it,
  82.      * and if it breaks, we'll remember not to use it again.
  83.      * @param stmtConfig The configuration to apply to statements when they are prepared.
  84.      */
  85.     public QueryRunner(final DataSource ds, final boolean pmdKnownBroken, final StatementConfiguration stmtConfig) {
  86.         super(ds, pmdKnownBroken, stmtConfig);
  87.     }

  88.     /**
  89.      * Constructor for QueryRunner that takes a {@code DataSource} to use and a {@code StatementConfiguration}.
  90.      *
  91.      * Methods that do not take a {@code Connection} parameter will retrieve connections from this
  92.      * {@code DataSource}.
  93.      *
  94.      * @param ds The {@code DataSource} to retrieve connections from.
  95.      * @param stmtConfig The configuration to apply to statements when they are prepared.
  96.      */
  97.     public QueryRunner(final DataSource ds, final StatementConfiguration stmtConfig) {
  98.         super(ds, stmtConfig);
  99.     }

  100.     /**
  101.      * Constructor for QueryRunner that takes a {@code StatementConfiguration} to configure statements when
  102.      * preparing them.
  103.      *
  104.      * @param stmtConfig The configuration to apply to statements when they are prepared.
  105.      */
  106.     public QueryRunner(final StatementConfiguration stmtConfig) {
  107.         super(stmtConfig);
  108.     }

  109.     /**
  110.      * Execute a batch of SQL INSERT, UPDATE, or DELETE queries.
  111.      *
  112.      * @param conn The Connection to use to run the query.  The caller is
  113.      * responsible for closing this Connection.
  114.      * @param sql The SQL to execute.
  115.      * @param params An array of query replacement parameters.  Each row in
  116.      * this array is one set of batch replacement values.
  117.      * @return The number of rows updated per statement.
  118.      * @throws SQLException if a database access error occurs
  119.      * @since 1.1
  120.      */
  121.     public int[] batch(final Connection conn, final String sql, final Object[][] params) throws SQLException {
  122.         if (conn == null) {
  123.             throw new SQLException("Null connection");
  124.         }

  125.         if (sql == null) {
  126.             throw new SQLException("Null SQL statement");
  127.         }

  128.         if (params == null) {
  129.             throw new SQLException("Null parameters. If parameters aren't need, pass an empty array.");
  130.         }

  131.         PreparedStatement stmt = null;
  132.         ParameterMetaData pmd = null;
  133.         int[] rows = null;
  134.         try {
  135.             stmt = this.prepareStatement(conn, sql);
  136.             // When the batch size is large, prefetching parameter metadata before filling
  137.             // the statement can reduce lots of JDBC communications.
  138.             pmd = this.getParameterMetaData(stmt);

  139.             for (final Object[] param : params) {
  140.                 this.fillStatement(stmt, pmd, param);
  141.                 stmt.addBatch();
  142.             }
  143.             rows = stmt.executeBatch();

  144.         } catch (final SQLException e) {
  145.             this.rethrow(e, sql, (Object[])params);
  146.         } finally {
  147.             close(stmt);
  148.         }

  149.         return rows;
  150.     }

  151.     /**
  152.      * Execute a batch of SQL INSERT, UPDATE, or DELETE queries.  The
  153.      * {@code Connection} is retrieved from the {@code DataSource}
  154.      * set in the constructor.  This {@code Connection} must be in
  155.      * auto-commit mode or the update will not be saved.
  156.      *
  157.      * @param sql The SQL to execute.
  158.      * @param params An array of query replacement parameters.  Each row in
  159.      * this array is one set of batch replacement values.
  160.      * @return The number of rows updated per statement.
  161.      * @throws SQLException if a database access error occurs
  162.      * @since 1.1
  163.      */
  164.     public int[] batch(final String sql, final Object[][] params) throws SQLException {
  165.         try (Connection conn = this.prepareConnection()) {
  166.             return this.batch(conn, sql, params);
  167.         }
  168.     }

  169.     /**
  170.      * Execute an SQL statement, including a stored procedure call, which does
  171.      * not return any result sets.
  172.      * Any parameters which are instances of {@link OutParameter} will be
  173.      * registered as OUT parameters.
  174.      * <p>
  175.      * Use this method when invoking a stored procedure with OUT parameters
  176.      * that does not return any result sets.  If you are not invoking a stored
  177.      * procedure, or the stored procedure has no OUT parameters, consider using
  178.      * {@link #update(java.sql.Connection, String, Object...) }.
  179.      * If the stored procedure returns result sets, use
  180.      * {@link #execute(java.sql.Connection, String, org.apache.commons.dbutils.ResultSetHandler, Object...) }.
  181.      *
  182.      * @param conn The connection to use to run the query.
  183.      * @param sql The SQL to execute.
  184.      * @param params The query replacement parameters.
  185.      * @return The number of rows updated.
  186.      * @throws SQLException if a database access error occurs
  187.      */
  188.     public int execute(final Connection conn, final String sql, final Object... params) throws SQLException {
  189.         if (conn == null) {
  190.             throw new SQLException("Null connection");
  191.         }

  192.         if (sql == null) {
  193.             throw new SQLException("Null SQL statement");
  194.         }

  195.         CallableStatement stmt = null;
  196.         int rows = 0;

  197.         try {
  198.             stmt = this.prepareCall(conn, sql);
  199.             this.fillStatement(stmt, params);
  200.             stmt.execute();
  201.             rows = stmt.getUpdateCount();
  202.             this.retrieveOutParameters(stmt, params);

  203.         } catch (final SQLException e) {
  204.             this.rethrow(e, sql, params);

  205.         } finally {
  206.             close(stmt);
  207.         }

  208.         return rows;
  209.     }

  210.     /**
  211.      * Execute an SQL statement, including a stored procedure call, which
  212.      * returns one or more result sets.
  213.      * Any parameters which are instances of {@link OutParameter} will be
  214.      * registered as OUT parameters.
  215.      * <p>
  216.      * Use this method when: a) running SQL statements that return multiple
  217.      * result sets; b) invoking a stored procedure that return result
  218.      * sets and OUT parameters.  Otherwise you may wish to use
  219.      * {@link #query(java.sql.Connection, String, org.apache.commons.dbutils.ResultSetHandler, Object...) }
  220.      * (if there are no OUT parameters) or
  221.      * {@link #execute(java.sql.Connection, String, Object...) }
  222.      * (if there are no result sets).
  223.      *
  224.      * @param <T> The type of object that the handler returns
  225.      * @param conn The connection to use to run the query.
  226.      * @param sql The SQL to execute.
  227.      * @param rsh The result set handler
  228.      * @param params The query replacement parameters.
  229.      * @return A list of objects generated by the handler
  230.      * @throws SQLException if a database access error occurs
  231.      */
  232.     public <T> List<T> execute(final Connection conn, final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
  233.         if (conn == null) {
  234.             throw new SQLException("Null connection");
  235.         }

  236.         if (sql == null) {
  237.             throw new SQLException("Null SQL statement");
  238.         }

  239.         if (rsh == null) {
  240.             throw new SQLException("Null ResultSetHandler");
  241.         }

  242.         CallableStatement stmt = null;
  243.         final List<T> results = new LinkedList<>();

  244.         try {
  245.             stmt = this.prepareCall(conn, sql);
  246.             this.fillStatement(stmt, params);
  247.             boolean moreResultSets = stmt.execute();
  248.             // Handle multiple result sets by passing them through the handler
  249.             // retaining the final result
  250.             while (moreResultSets) {
  251.                 try (@SuppressWarnings("resource")
  252.                 // assume the ResultSet wrapper properly closes
  253.                 ResultSet resultSet = this.wrap(stmt.getResultSet())) {
  254.                     results.add(rsh.handle(resultSet));
  255.                     moreResultSets = stmt.getMoreResults();
  256.                 }
  257.             }
  258.             this.retrieveOutParameters(stmt, params);

  259.         } catch (final SQLException e) {
  260.             this.rethrow(e, sql, params);

  261.         } finally {
  262.             close(stmt);
  263.         }

  264.         return results;
  265.     }

  266.     /**
  267.      * Execute an SQL statement, including a stored procedure call, which does
  268.      * not return any result sets.
  269.      * Any parameters which are instances of {@link OutParameter} will be
  270.      * registered as OUT parameters.
  271.      * <p>
  272.      * Use this method when invoking a stored procedure with OUT parameters
  273.      * that does not return any result sets.  If you are not invoking a stored
  274.      * procedure, or the stored procedure has no OUT parameters, consider using
  275.      * {@link #update(String, Object...) }.
  276.      * If the stored procedure returns result sets, use
  277.      * {@link #execute(String, org.apache.commons.dbutils.ResultSetHandler, Object...) }.
  278.      * <p>
  279.      * The {@code Connection} is retrieved from the {@code DataSource}
  280.      * set in the constructor.  This {@code Connection} must be in
  281.      * auto-commit mode or the update will not be saved.
  282.      *
  283.      * @param sql The SQL statement to execute.
  284.      * @param params Initializes the CallableStatement's parameters (i.e. '?').
  285.      * @throws SQLException if a database access error occurs
  286.      * @return The number of rows updated.
  287.      */
  288.     public int execute(final String sql, final Object... params) throws SQLException {
  289.         try (Connection conn = this.prepareConnection()) {
  290.             return this.execute(conn, sql, params);
  291.         }
  292.     }

  293.     /**
  294.      * Execute an SQL statement, including a stored procedure call, which
  295.      * returns one or more result sets.
  296.      * Any parameters which are instances of {@link OutParameter} will be
  297.      * registered as OUT parameters.
  298.      * <p>
  299.      * Use this method when: a) running SQL statements that return multiple
  300.      * result sets; b) invoking a stored procedure that return result
  301.      * sets and OUT parameters.  Otherwise you may wish to use
  302.      * {@link #query(String, org.apache.commons.dbutils.ResultSetHandler, Object...) }
  303.      * (if there are no OUT parameters) or
  304.      * {@link #execute(String, Object...) }
  305.      * (if there are no result sets).
  306.      *
  307.      * @param <T> The type of object that the handler returns
  308.      * @param sql The SQL to execute.
  309.      * @param rsh The result set handler
  310.      * @param params The query replacement parameters.
  311.      * @return A list of objects generated by the handler
  312.      * @throws SQLException if a database access error occurs
  313.      */
  314.     public <T> List<T> execute(final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
  315.         try (Connection conn = this.prepareConnection()) {
  316.             return this.execute(conn, sql, rsh, params);
  317.         }
  318.     }

  319.     /**
  320.      * Execute an SQL INSERT query without replacement parameters.
  321.      * @param <T> The type of object that the handler returns
  322.      * @param conn The connection to use to run the query.
  323.      * @param sql The SQL to execute.
  324.      * @param rsh The handler used to create the result object from
  325.      * the {@code ResultSet} of auto-generated keys.
  326.      * @return An object generated by the handler.
  327.      * @throws SQLException if a database access error occurs
  328.      * @since 1.6
  329.      */
  330.     public <T> T insert(final Connection conn, final String sql, final ResultSetHandler<T> rsh) throws SQLException {
  331.         return insert(conn, sql, rsh, (Object[]) null);
  332.     }

  333.     /**
  334.      * Execute an SQL INSERT query.
  335.      * @param <T> The type of object that the handler returns
  336.      * @param conn The connection to use to run the query.
  337.      * @param sql The SQL to execute.
  338.      * @param rsh The handler used to create the result object from
  339.      * the {@code ResultSet} of auto-generated keys.
  340.      * @param params The query replacement parameters.
  341.      * @return An object generated by the handler.
  342.      * @throws SQLException if a database access error occurs
  343.      * @since 1.6
  344.      */
  345.     public <T> T insert(final Connection conn, final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
  346.         if (conn == null) {
  347.             throw new SQLException("Null connection");
  348.         }

  349.         if (sql == null) {
  350.             throw new SQLException("Null SQL statement");
  351.         }

  352.         if (rsh == null) {
  353.             throw new SQLException("Null ResultSetHandler");
  354.         }

  355.         Statement stmt = null;
  356.         T generatedKeys = null;

  357.         try {
  358.             if (params != null && params.length > 0) {
  359.                 final PreparedStatement ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
  360.                 stmt = ps;
  361.                 this.fillStatement(ps, params);
  362.                 ps.executeUpdate();
  363.             } else {
  364.                 stmt = conn.createStatement();
  365.                 stmt.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
  366.             }
  367.             try (ResultSet resultSet = stmt.getGeneratedKeys()) {
  368.                 generatedKeys = rsh.handle(resultSet);
  369.             }
  370.         } catch (final SQLException e) {
  371.             this.rethrow(e, sql, params);
  372.         } finally {
  373.             close(stmt);
  374.         }

  375.         return generatedKeys;
  376.     }

  377.     /**
  378.      * Executes the given INSERT SQL without any replacement parameters.
  379.      * The {@code Connection} is retrieved from the
  380.      * {@code DataSource} set in the constructor.
  381.      * @param <T> The type of object that the handler returns
  382.      * @param sql The SQL statement to execute.
  383.      * @param rsh The handler used to create the result object from
  384.      * the {@code ResultSet} of auto-generated keys.
  385.      * @return An object generated by the handler.
  386.      * @throws SQLException if a database access error occurs
  387.      * @since 1.6
  388.      */
  389.     public <T> T insert(final String sql, final ResultSetHandler<T> rsh) throws SQLException {
  390.         try (Connection conn = this.prepareConnection()) {
  391.             return insert(conn, sql, rsh, (Object[]) null);
  392.         }
  393.     }

  394.     /**
  395.      * Executes the given INSERT SQL statement. The
  396.      * {@code Connection} is retrieved from the {@code DataSource}
  397.      * set in the constructor.  This {@code Connection} must be in
  398.      * auto-commit mode or the insert will not be saved.
  399.      * @param <T> The type of object that the handler returns
  400.      * @param sql The SQL statement to execute.
  401.      * @param rsh The handler used to create the result object from
  402.      * the {@code ResultSet} of auto-generated keys.
  403.      * @param params Initializes the PreparedStatement's IN (i.e. '?')
  404.      * @return An object generated by the handler.
  405.      * @throws SQLException if a database access error occurs
  406.      * @since 1.6
  407.      */
  408.     public <T> T insert(final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
  409.         try (Connection conn = this.prepareConnection()) {
  410.             return insert(conn, sql, rsh, params);
  411.         }
  412.     }

  413.     /**
  414.      * Executes the given batch of INSERT SQL statements.
  415.      * @param <T> The type of object that the handler returns
  416.      * @param conn The connection to use to run the query.
  417.      * @param sql The SQL to execute.
  418.      * @param rsh The handler used to create the result object from
  419.      * the {@code ResultSet} of auto-generated keys.
  420.      * @param params The query replacement parameters.
  421.      * @return The result generated by the handler.
  422.      * @throws SQLException if a database access error occurs
  423.      * @since 1.6
  424.      */
  425.     public <T> T insertBatch(final Connection conn, final String sql, final ResultSetHandler<T> rsh, final Object[][] params) throws SQLException {
  426.         if (conn == null) {
  427.             throw new SQLException("Null connection");
  428.         }

  429.         if (sql == null) {
  430.             throw new SQLException("Null SQL statement");
  431.         }

  432.         if (params == null) {
  433.             throw new SQLException("Null parameters. If parameters aren't need, pass an empty array.");
  434.         }

  435.         PreparedStatement stmt = null;
  436.         T generatedKeys = null;
  437.         try {
  438.             stmt = this.prepareStatement(conn, sql, Statement.RETURN_GENERATED_KEYS);

  439.             for (final Object[] param : params) {
  440.                 this.fillStatement(stmt, param);
  441.                 stmt.addBatch();
  442.             }
  443.             stmt.executeBatch();
  444.             try (ResultSet resultSet = stmt.getGeneratedKeys()) {
  445.                 generatedKeys = rsh.handle(resultSet);
  446.             }
  447.         } catch (final SQLException e) {
  448.             this.rethrow(e, sql, (Object[])params);
  449.         } finally {
  450.             close(stmt);
  451.         }

  452.         return generatedKeys;
  453.     }

  454.     /**
  455.      * Executes the given batch of INSERT SQL statements. The
  456.      * {@code Connection} is retrieved from the {@code DataSource}
  457.      * set in the constructor.  This {@code Connection} must be in
  458.      * auto-commit mode or the insert will not be saved.
  459.      * @param <T> The type of object that the handler returns
  460.      * @param sql The SQL statement to execute.
  461.      * @param rsh The handler used to create the result object from
  462.      * the {@code ResultSet} of auto-generated keys.
  463.      * @param params Initializes the PreparedStatement's IN (i.e. '?')
  464.      * @return The result generated by the handler.
  465.      * @throws SQLException if a database access error occurs
  466.      * @since 1.6
  467.      */
  468.     public <T> T insertBatch(final String sql, final ResultSetHandler<T> rsh, final Object[][] params) throws SQLException {
  469.         try (Connection conn = this.prepareConnection()) {
  470.             return insertBatch(conn, sql, rsh, params);
  471.         }
  472.     }

  473.     /**
  474.      * Execute an SQL SELECT query with a single replacement parameter. The
  475.      * caller is responsible for closing the connection.
  476.      * @param <T> The type of object that the handler returns
  477.      * @param conn The connection to execute the query in.
  478.      * @param sql The query to execute.
  479.      * @param param The replacement parameter.
  480.      * @param rsh The handler that converts the results into an object.
  481.      * @return The object returned by the handler.
  482.      * @throws SQLException if a database access error occurs
  483.      * @deprecated Use {@link #query(Connection, String, ResultSetHandler, Object...)}
  484.      */
  485.     @Deprecated
  486.     public <T> T query(final Connection conn, final String sql, final Object param, final ResultSetHandler<T> rsh) throws SQLException {
  487.         return this.<T>query(conn, sql, rsh, param);
  488.     }

  489.     /**
  490.      * Execute an SQL SELECT query with replacement parameters.  The
  491.      * caller is responsible for closing the connection.
  492.      * @param <T> The type of object that the handler returns
  493.      * @param conn The connection to execute the query in.
  494.      * @param sql The query to execute.
  495.      * @param params The replacement parameters.
  496.      * @param rsh The handler that converts the results into an object.
  497.      * @return The object returned by the handler.
  498.      * @throws SQLException if a database access error occurs
  499.      * @deprecated Use {@link #query(Connection,String,ResultSetHandler,Object...)} instead
  500.      */
  501.     @Deprecated
  502.     public <T> T query(final Connection conn, final String sql, final Object[] params, final ResultSetHandler<T> rsh) throws SQLException {
  503.         return this.<T>query(conn, sql, rsh, params);
  504.     }

  505.     /**
  506.      * Execute an SQL SELECT query without any replacement parameters.  The
  507.      * caller is responsible for closing the connection.
  508.      * @param <T> The type of object that the handler returns
  509.      * @param conn The connection to execute the query in.
  510.      * @param sql The query to execute.
  511.      * @param rsh The handler that converts the results into an object.
  512.      * @return The object returned by the handler.
  513.      * @throws SQLException if a database access error occurs
  514.      */
  515.     public <T> T query(final Connection conn, final String sql, final ResultSetHandler<T> rsh) throws SQLException {
  516.         return this.<T>query(conn, sql, rsh, (Object[]) null);
  517.     }

  518.     /**
  519.      * Execute an SQL SELECT query with replacement parameters.  The
  520.      * caller is responsible for closing the connection.
  521.      * @param <T> The type of object that the handler returns
  522.      * @param conn The connection to execute the query in.
  523.      * @param sql The query to execute.
  524.      * @param rsh The handler that converts the results into an object.
  525.      * @param params The replacement parameters.
  526.      * @return The object returned by the handler.
  527.      * @throws SQLException if a database access error occurs
  528.      */
  529.     public <T> T query(final Connection conn, final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
  530.         if (conn == null) {
  531.             throw new SQLException("Null connection");
  532.         }

  533.         if (sql == null) {
  534.             throw new SQLException("Null SQL statement");
  535.         }

  536.         if (rsh == null) {
  537.             throw new SQLException("Null ResultSetHandler");
  538.         }

  539.         Statement stmt = null;
  540.         ResultSet resultSet = null;
  541.         T result = null;

  542.         try {
  543.             if (params != null && params.length > 0) {
  544.                 final PreparedStatement ps = this.prepareStatement(conn, sql);
  545.                 stmt = ps;
  546.                 this.fillStatement(ps, params);
  547.                 resultSet = this.wrap(ps.executeQuery());
  548.             } else {
  549.                 stmt = conn.createStatement();
  550.                 resultSet = this.wrap(stmt.executeQuery(sql));
  551.             }
  552.             result = rsh.handle(resultSet);

  553.         } catch (final SQLException e) {
  554.             this.rethrow(e, sql, params);

  555.         } finally {
  556.             closeQuietly(resultSet);
  557.             closeQuietly(stmt);
  558.         }

  559.         return result;
  560.     }

  561.     /**
  562.      * Executes the given SELECT SQL with a single replacement parameter.
  563.      * The {@code Connection} is retrieved from the
  564.      * {@code DataSource} set in the constructor.
  565.      * @param <T> The type of object that the handler returns
  566.      * @param sql The SQL statement to execute.
  567.      * @param param The replacement parameter.
  568.      * @param rsh The handler used to create the result object from
  569.      * the {@code ResultSet}.
  570.      *
  571.      * @return An object generated by the handler.
  572.      * @throws SQLException if a database access error occurs
  573.      * @deprecated Use {@link #query(String, ResultSetHandler, Object...)}
  574.      */
  575.     @Deprecated
  576.     public <T> T query(final String sql, final Object param, final ResultSetHandler<T> rsh) throws SQLException {
  577.         try (Connection conn = this.prepareConnection()) {
  578.             return this.<T>query(conn, sql, rsh, param);
  579.         }
  580.     }

  581.     /**
  582.      * Executes the given SELECT SQL query and returns a result object.
  583.      * The {@code Connection} is retrieved from the
  584.      * {@code DataSource} set in the constructor.
  585.      * @param <T> The type of object that the handler returns
  586.      * @param sql The SQL statement to execute.
  587.      * @param params Initialize the PreparedStatement's IN parameters with
  588.      * this array.
  589.      *
  590.      * @param rsh The handler used to create the result object from
  591.      * the {@code ResultSet}.
  592.      *
  593.      * @return An object generated by the handler.
  594.      * @throws SQLException if a database access error occurs
  595.      * @deprecated Use {@link #query(String, ResultSetHandler, Object...)}
  596.      */
  597.     @Deprecated
  598.     public <T> T query(final String sql, final Object[] params, final ResultSetHandler<T> rsh) throws SQLException {
  599.         try (Connection conn = this.prepareConnection()) {
  600.             return this.<T>query(conn, sql, rsh, params);
  601.         }
  602.     }

  603.     /**
  604.      * Executes the given SELECT SQL without any replacement parameters.
  605.      * The {@code Connection} is retrieved from the
  606.      * {@code DataSource} set in the constructor.
  607.      * @param <T> The type of object that the handler returns
  608.      * @param sql The SQL statement to execute.
  609.      * @param rsh The handler used to create the result object from
  610.      * the {@code ResultSet}.
  611.      *
  612.      * @return An object generated by the handler.
  613.      * @throws SQLException if a database access error occurs
  614.      */
  615.     public <T> T query(final String sql, final ResultSetHandler<T> rsh) throws SQLException {
  616.         try (Connection conn = this.prepareConnection()) {
  617.             return this.<T>query(conn, sql, rsh, (Object[]) null);
  618.         }
  619.     }

  620.     /**
  621.      * Executes the given SELECT SQL query and returns a result object.
  622.      * The {@code Connection} is retrieved from the
  623.      * {@code DataSource} set in the constructor.
  624.      * @param <T> The type of object that the handler returns
  625.      * @param sql The SQL statement to execute.
  626.      * @param rsh The handler used to create the result object from
  627.      * the {@code ResultSet}.
  628.      * @param params Initialize the PreparedStatement's IN parameters with
  629.      * this array.
  630.      * @return An object generated by the handler.
  631.      * @throws SQLException if a database access error occurs
  632.      */
  633.     public <T> T query(final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
  634.         try (Connection conn = this.prepareConnection()) {
  635.             return this.<T>query(conn, sql, rsh, params);
  636.         }
  637.     }

  638.     /**
  639.      * Set the value on all the {@link OutParameter} instances in the
  640.      * {@code params} array using the OUT parameter values from the
  641.      * {@code stmt}.
  642.      * @param stmt the statement from which to retrieve OUT parameter values
  643.      * @param params the parameter array for the statement invocation
  644.      * @throws SQLException when the value could not be retrieved from the
  645.      * statement.
  646.      */
  647.     private void retrieveOutParameters(final CallableStatement stmt, final Object[] params) throws SQLException {
  648.         if (params != null) {
  649.             for (int i = 0; i < params.length; i++) {
  650.                 if (params[i] instanceof OutParameter) {
  651.                     ((OutParameter<?>) params[i]).setValue(stmt, i + 1);
  652.                 }
  653.             }
  654.         }
  655.     }

  656.     /**
  657.      * Execute an SQL INSERT, UPDATE, or DELETE query without replacement
  658.      * parameters.
  659.      *
  660.      * @param conn The connection to use to run the query.
  661.      * @param sql The SQL to execute.
  662.      * @return The number of rows updated.
  663.      * @throws SQLException if a database access error occurs
  664.      */
  665.     public int update(final Connection conn, final String sql) throws SQLException {
  666.         return this.update(conn, sql, (Object[]) null);
  667.     }

  668.     /**
  669.      * Execute an SQL INSERT, UPDATE, or DELETE query with a single replacement
  670.      * parameter.
  671.      *
  672.      * @param conn The connection to use to run the query.
  673.      * @param sql The SQL to execute.
  674.      * @param param The replacement parameter.
  675.      * @return The number of rows updated.
  676.      * @throws SQLException if a database access error occurs
  677.      */
  678.     public int update(final Connection conn, final String sql, final Object param) throws SQLException {
  679.         return this.update(conn, sql, new Object[] { param });
  680.     }

  681.     /**
  682.      * Execute an SQL INSERT, UPDATE, or DELETE query.
  683.      *
  684.      * @param conn The connection to use to run the query.
  685.      * @param sql The SQL to execute.
  686.      * @param params The query replacement parameters.
  687.      * @return The number of rows updated.
  688.      * @throws SQLException if a database access error occurs
  689.      */
  690.     public int update(final Connection conn, final String sql, final Object... params) throws SQLException {
  691.         if (conn == null) {
  692.             throw new SQLException("Null connection");
  693.         }

  694.         if (sql == null) {
  695.             throw new SQLException("Null SQL statement");
  696.         }

  697.         Statement stmt = null;
  698.         int rows = 0;

  699.         try {
  700.             if (params != null && params.length > 0) {
  701.                 final PreparedStatement ps = this.prepareStatement(conn, sql);
  702.                 stmt = ps;
  703.                 this.fillStatement(ps, params);
  704.                 rows = ps.executeUpdate();
  705.             } else {
  706.                 stmt = conn.createStatement();
  707.                 rows = stmt.executeUpdate(sql);
  708.             }

  709.         } catch (final SQLException e) {
  710.             this.rethrow(e, sql, params);

  711.         } finally {
  712.             close(stmt);
  713.         }

  714.         return rows;
  715.     }

  716.     /**
  717.      * Executes the given INSERT, UPDATE, or DELETE SQL statement without
  718.      * any replacement parameters. The {@code Connection} is retrieved
  719.      * from the {@code DataSource} set in the constructor.  This
  720.      * {@code Connection} must be in auto-commit mode or the update will
  721.      * not be saved.
  722.      *
  723.      * @param sql The SQL statement to execute.
  724.      * @throws SQLException if a database access error occurs
  725.      * @return The number of rows updated.
  726.      */
  727.     public int update(final String sql) throws SQLException {
  728.         try (Connection conn = this.prepareConnection()) {
  729.             return this.update(conn, sql, (Object[]) null);
  730.         }
  731.     }

  732.     /**
  733.      * Executes the given INSERT, UPDATE, or DELETE SQL statement with
  734.      * a single replacement parameter.  The {@code Connection} is
  735.      * retrieved from the {@code DataSource} set in the constructor.
  736.      * This {@code Connection} must be in auto-commit mode or the
  737.      * update will not be saved.
  738.      *
  739.      * @param sql The SQL statement to execute.
  740.      * @param param The replacement parameter.
  741.      * @throws SQLException if a database access error occurs
  742.      * @return The number of rows updated.
  743.      */
  744.     public int update(final String sql, final Object param) throws SQLException {
  745.         try (Connection conn = this.prepareConnection()) {
  746.             return this.update(conn, sql, param);
  747.         }
  748.     }

  749.     /**
  750.      * Executes the given INSERT, UPDATE, or DELETE SQL statement.  The
  751.      * {@code Connection} is retrieved from the {@code DataSource}
  752.      * set in the constructor.  This {@code Connection} must be in
  753.      * auto-commit mode or the update will not be saved.
  754.      *
  755.      * @param sql The SQL statement to execute.
  756.      * @param params Initializes the PreparedStatement's IN (i.e. '?')
  757.      * parameters.
  758.      * @throws SQLException if a database access error occurs
  759.      * @return The number of rows updated.
  760.      */
  761.     public int update(final String sql, final Object... params) throws SQLException {
  762.         try (Connection conn = this.prepareConnection()) {
  763.             return this.update(conn, sql, params);
  764.         }
  765.     }
  766. }