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/30 15:14:02 UTC
[commons-dbutils] branch master updated: Use standard Javadoc @since tag format
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 c442515 Use standard Javadoc @since tag format
c442515 is described below
commit c442515990f431cd33afdfedcb1bcc327967c1d0
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Tue Aug 30 11:13:58 2022 -0400
Use standard Javadoc @since tag format
---
.../commons/dbutils/AbstractQueryRunner.java | 1270 +++++++++---------
.../apache/commons/dbutils/AsyncQueryRunner.java | 1382 ++++++++++----------
.../apache/commons/dbutils/BasicRowProcessor.java | 2 +-
.../org/apache/commons/dbutils/BeanProcessor.java | 2 +-
.../java/org/apache/commons/dbutils/DbUtils.java | 852 ++++++------
.../org/apache/commons/dbutils/QueryLoader.java | 284 ++--
.../org/apache/commons/dbutils/QueryRunner.java | 4 +-
.../apache/commons/dbutils/ResultSetIterator.java | 282 ++--
.../dbutils/handlers/AbstractKeyedHandler.java | 174 +--
.../commons/dbutils/handlers/BeanMapHandler.java | 368 +++---
.../dbutils/handlers/ColumnListHandler.java | 208 +--
.../commons/dbutils/handlers/KeyedHandler.java | 320 ++---
12 files changed, 2574 insertions(+), 2574 deletions(-)
diff --git a/src/main/java/org/apache/commons/dbutils/AbstractQueryRunner.java b/src/main/java/org/apache/commons/dbutils/AbstractQueryRunner.java
index 8415173..c6492c9 100644
--- a/src/main/java/org/apache/commons/dbutils/AbstractQueryRunner.java
+++ b/src/main/java/org/apache/commons/dbutils/AbstractQueryRunner.java
@@ -1,635 +1,635 @@
-/*
- * 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.beans.IntrospectionException;
-import java.beans.Introspector;
-import java.beans.PropertyDescriptor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.sql.CallableStatement;
-import java.sql.Connection;
-import java.sql.ParameterMetaData;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.SQLFeatureNotSupportedException;
-import java.sql.Statement;
-import java.sql.Types;
-import java.util.Arrays;
-
-import javax.sql.DataSource;
-
-/**
- * The base class for QueryRunner & AsyncQueryRunner. This class is thread safe.
- *
- * @since 1.4 (mostly extracted from QueryRunner)
- */
-public abstract class AbstractQueryRunner {
- /**
- * Is {@link ParameterMetaData#getParameterType(int)} broken (have we tried
- * it yet)?
- */
- private volatile boolean pmdKnownBroken = false;
-
- /**
- * The DataSource to retrieve connections from.
- * @deprecated Access to this field should be through {@link #getDataSource()}.
- */
- @Deprecated
- protected final DataSource ds;
-
- /**
- * Configuration to use when preparing statements.
- */
- private final StatementConfiguration stmtConfig;
-
- /**
- * Default constructor, sets pmdKnownBroken to false, ds to null and stmtConfig to null.
- */
- public AbstractQueryRunner() {
- ds = null;
- this.stmtConfig = null;
- }
-
- /**
- * Constructor to control the use of {@code ParameterMetaData}.
- *
- * @param pmdKnownBroken
- * Some drivers don't support
- * {@link 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 AbstractQueryRunner(final boolean pmdKnownBroken) {
- this.pmdKnownBroken = pmdKnownBroken;
- ds = null;
- this.stmtConfig = null;
- }
-
- /**
- * Constructor to provide a {@code DataSource}. 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 AbstractQueryRunner(final DataSource ds) {
- this.ds = ds;
- this.stmtConfig = null;
- }
-
- /**
- * Constructor to provide a {@code DataSource} and control 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 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 AbstractQueryRunner(final DataSource ds, final boolean pmdKnownBroken) {
- this.pmdKnownBroken = pmdKnownBroken;
- this.ds = ds;
- this.stmtConfig = null;
- }
-
- /**
- * 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 AbstractQueryRunner(final DataSource ds, final boolean pmdKnownBroken, final StatementConfiguration stmtConfig) {
- this.pmdKnownBroken = pmdKnownBroken;
- this.ds = ds;
- this.stmtConfig = stmtConfig;
- }
-
- /**
- * 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 AbstractQueryRunner(final DataSource ds, final StatementConfiguration stmtConfig) {
- this.ds = ds;
- this.stmtConfig = stmtConfig;
- }
-
- /**
- * 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 AbstractQueryRunner(final StatementConfiguration stmtConfig) {
- this.ds = null;
- this.stmtConfig = stmtConfig;
- }
-
- /**
- * Close a {@code Connection}. This implementation avoids closing if
- * null and does <strong>not</strong> suppress any exceptions. Subclasses
- * can override to provide special handling like logging.
- *
- * @param conn
- * Connection to close
- * @throws SQLException
- * if a database access error occurs
- * @since DbUtils 1.1
- */
- protected void close(final Connection conn) throws SQLException {
- DbUtils.close(conn);
- }
-
- /**
- * Close a {@code ResultSet}. This implementation avoids closing if
- * null and does <strong>not</strong> suppress any exceptions. Subclasses
- * can override to provide special handling like logging.
- *
- * @param rs
- * ResultSet to close
- * @throws SQLException
- * if a database access error occurs
- * @since DbUtils 1.1
- */
- protected void close(final ResultSet rs) throws SQLException {
- DbUtils.close(rs);
- }
-
- /**
- * Close a {@code Statement}. This implementation avoids closing if
- * null and does <strong>not</strong> suppress any exceptions. Subclasses
- * can override to provide special handling like logging.
- *
- * @param stmt
- * Statement to close
- * @throws SQLException
- * if a database access error occurs
- * @since DbUtils 1.1
- */
- protected void close(final Statement stmt) throws SQLException {
- DbUtils.close(stmt);
- }
-
- /**
- * Calls {@link DbUtils#closeQuietly(Connection)}.
- *
- * @param conn Connection to close.
- * @since 2.0
- */
- protected void closeQuietly(final Connection conn) {
- DbUtils.closeQuietly(conn);
- }
-
- /**
- * Calls {@link DbUtils#closeQuietly(ResultSet)}.
- *
- * @param rs ResultSet to close.
- * @since 2.0
- */
- protected void closeQuietly(final ResultSet rs) {
- DbUtils.closeQuietly(rs);
- }
-
- /**
- * Calls {@link DbUtils#closeQuietly(Statement)}.
- *
- * @param statement ResultSet to close.
- * @since 2.0
- */
- protected void closeQuietly(final Statement statement) {
- DbUtils.closeQuietly(statement);
- }
-
- private void configureStatement(final Statement stmt) throws SQLException {
-
- if (stmtConfig != null) {
- if (stmtConfig.isFetchDirectionSet()) {
- stmt.setFetchDirection(stmtConfig.getFetchDirection());
- }
-
- if (stmtConfig.isFetchSizeSet()) {
- stmt.setFetchSize(stmtConfig.getFetchSize());
- }
-
- if (stmtConfig.isMaxFieldSizeSet()) {
- stmt.setMaxFieldSize(stmtConfig.getMaxFieldSize());
- }
-
- if (stmtConfig.isMaxRowsSet()) {
- stmt.setMaxRows(stmtConfig.getMaxRows());
- }
-
- if (stmtConfig.isQueryTimeoutSet()) {
- stmt.setQueryTimeout(stmtConfig.getQueryTimeout());
- }
- }
- }
-
- /**
- * Fill the {@code PreparedStatement} replacement parameters with the
- * given objects.
- *
- * @param stmt
- * PreparedStatement to fill
- * @param params
- * Query replacement parameters; {@code null} is a valid
- * value to pass in.
- * @throws SQLException
- * if a database access error occurs
- */
- public void fillStatement(final PreparedStatement stmt, final Object... params)
- throws SQLException {
-
- // check the parameter count, if we can
- ParameterMetaData pmd = null;
- if (!pmdKnownBroken) {
- try {
- pmd = stmt.getParameterMetaData();
- if (pmd == null) { // can be returned by implementations that don't support the method
- pmdKnownBroken = true;
- } else {
- final int stmtCount = pmd.getParameterCount();
- final int paramsCount = params == null ? 0 : params.length;
-
- if (stmtCount != paramsCount) {
- throw new SQLException("Wrong number of parameters: expected "
- + stmtCount + ", was given " + paramsCount);
- }
- }
- } catch (final SQLFeatureNotSupportedException ex) {
- pmdKnownBroken = true;
- }
- // TODO see DBUTILS-117: would it make sense to catch any other SQLEx types here?
- }
-
- // nothing to do here
- if (params == null) {
- return;
- }
-
- CallableStatement call = null;
- if (stmt instanceof CallableStatement) {
- call = (CallableStatement) stmt;
- }
-
- for (int i = 0; i < params.length; i++) {
- if (params[i] != null) {
- if (call != null && params[i] instanceof OutParameter) {
- ((OutParameter)params[i]).register(call, i + 1);
- } else {
- stmt.setObject(i + 1, params[i]);
- }
- } else {
- // VARCHAR works with many drivers regardless
- // of the actual column type. Oddly, NULL and
- // OTHER don't work with Oracle's drivers.
- int sqlType = Types.VARCHAR;
- if (!pmdKnownBroken) {
- // TODO see DBUTILS-117: does it make sense to catch SQLEx here?
- try {
- /*
- * It's not possible for pmdKnownBroken to change from
- * true to false, (once true, always true) so pmd cannot
- * be null here.
- */
- sqlType = pmd.getParameterType(i + 1);
- } catch (final SQLException e) {
- pmdKnownBroken = true;
- }
- }
- stmt.setNull(i + 1, sqlType);
- }
- }
- }
-
- /**
- * Fill the {@code PreparedStatement} replacement parameters with the
- * given object's bean property values.
- *
- * @param stmt
- * PreparedStatement to fill
- * @param bean
- * a JavaBean object
- * @param properties
- * an ordered array of properties; this gives the order to insert
- * values in the statement
- * @throws SQLException
- * if a database access error occurs
- */
- public void fillStatementWithBean(final PreparedStatement stmt, final Object bean,
- final PropertyDescriptor[] properties) throws SQLException {
- final Object[] params = new Object[properties.length];
- for (int i = 0; i < properties.length; i++) {
- final PropertyDescriptor property = properties[i];
- Object value = null;
- final Method method = property.getReadMethod();
- if (method == null) {
- throw new RuntimeException("No read method for bean property "
- + bean.getClass() + " " + property.getName());
- }
- try {
- value = method.invoke(bean);
- } catch (final IllegalArgumentException e) {
- throw new RuntimeException(
- "Couldn't invoke method with 0 arguments: " + method, e);
- } catch (final InvocationTargetException | IllegalAccessException e) {
- throw new RuntimeException("Couldn't invoke method: " + method,
- e);
- }
- params[i] = value;
- }
- fillStatement(stmt, params);
- }
-
- /**
- * Fill the {@code PreparedStatement} replacement parameters with the
- * given object's bean property values.
- *
- * @param stmt
- * PreparedStatement to fill
- * @param bean
- * A JavaBean object
- * @param propertyNames
- * An ordered array of property names (these should match the
- * getters/setters); this gives the order to insert values in the
- * statement
- * @throws SQLException
- * If a database access error occurs
- */
- public void fillStatementWithBean(final PreparedStatement stmt, final Object bean,
- final String... propertyNames) throws SQLException {
- PropertyDescriptor[] descriptors;
- try {
- descriptors = Introspector.getBeanInfo(bean.getClass())
- .getPropertyDescriptors();
- } catch (final IntrospectionException e) {
- throw new RuntimeException("Couldn't introspect bean "
- + bean.getClass().toString(), e);
- }
- final PropertyDescriptor[] sorted = new PropertyDescriptor[propertyNames.length];
- for (int i = 0; i < propertyNames.length; i++) {
- final String propertyName = propertyNames[i];
- if (propertyName == null) {
- throw new NullPointerException("propertyName can't be null: "
- + i);
- }
- boolean found = false;
- for (final PropertyDescriptor descriptor : descriptors) {
- if (propertyName.equals(descriptor.getName())) {
- sorted[i] = descriptor;
- found = true;
- break;
- }
- }
- if (!found) {
- throw new RuntimeException("Couldn't find bean property: "
- + bean.getClass() + " " + propertyName);
- }
- }
- fillStatementWithBean(stmt, bean, sorted);
- }
-
- /**
- * Returns the {@code DataSource} this runner is using.
- * {@code QueryRunner} methods always call this method to get the
- * {@code DataSource} so subclasses can provide specialized behavior.
- *
- * @return DataSource the runner is using
- */
- public DataSource getDataSource() {
- return this.ds;
- }
-
- /**
- * Some drivers don't support
- * {@link 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.
- *
- * @return the flag to skip (or not)
- * {@link ParameterMetaData#getParameterType(int) }
- * @since 1.4
- */
- public boolean isPmdKnownBroken() {
- return pmdKnownBroken;
- }
-
- /**
- * Factory method that creates and initializes a
- * {@code CallableStatement} object for the given SQL.
- * {@code QueryRunner} methods always call this method to prepare
- * callable statements for them. Subclasses can override this method to
- * provide special CallableStatement configuration if needed. This
- * implementation simply calls {@code conn.prepareCall(sql)}.
- *
- * @param conn
- * The {@code Connection} used to create the
- * {@code CallableStatement}
- * @param sql
- * The SQL statement to prepare.
- * @return An initialized {@code CallableStatement}.
- * @throws SQLException
- * if a database access error occurs
- */
- protected CallableStatement prepareCall(final Connection conn, final String sql)
- throws SQLException {
-
- return conn.prepareCall(sql);
- }
-
- /**
- * Factory method that creates and initializes a {@code Connection}
- * object. {@code QueryRunner} methods always call this method to
- * retrieve connections from its DataSource. Subclasses can override this
- * method to provide special {@code Connection} configuration if
- * needed. This implementation simply calls {@code ds.getConnection()}.
- *
- * @return An initialized {@code Connection}.
- * @throws SQLException
- * if a database access error occurs
- * @since DbUtils 1.1
- */
- protected Connection prepareConnection() throws SQLException {
- if (this.getDataSource() == null) {
- throw new SQLException(
- "QueryRunner requires a DataSource to be "
- + "invoked in this way, or a Connection should be passed in");
- }
- return this.getDataSource().getConnection();
- }
-
- /**
- * Factory method that creates and initializes a
- * {@code PreparedStatement} object for the given SQL.
- * {@code QueryRunner} methods always call this method to prepare
- * statements for them. Subclasses can override this method to provide
- * special PreparedStatement configuration if needed. This implementation
- * simply calls {@code conn.prepareStatement(sql)}.
- *
- * @param conn
- * The {@code Connection} used to create the
- * {@code PreparedStatement}
- * @param sql
- * The SQL statement to prepare.
- * @return An initialized {@code PreparedStatement}.
- * @throws SQLException
- * if a database access error occurs
- */
- protected PreparedStatement prepareStatement(final Connection conn, final String sql)
- throws SQLException {
-
- @SuppressWarnings("resource")
- final
- PreparedStatement ps = conn.prepareStatement(sql);
- try {
- configureStatement(ps);
- } catch (final SQLException e) {
- ps.close();
- throw e;
- }
- return ps;
- }
-
- /**
- * Factory method that creates and initializes a
- * {@code PreparedStatement} object for the given SQL.
- * {@code QueryRunner} methods always call this method to prepare
- * statements for them. Subclasses can override this method to provide
- * special PreparedStatement configuration if needed. This implementation
- * simply calls {@code conn.prepareStatement(sql, returnedKeys)}
- * which will result in the ability to retrieve the automatically-generated
- * keys from an auto_increment column.
- *
- * @param conn
- * The {@code Connection} used to create the
- * {@code PreparedStatement}
- * @param sql
- * The SQL statement to prepare.
- * @param returnedKeys
- * Flag indicating whether to return generated keys or not.
- *
- * @return An initialized {@code PreparedStatement}.
- * @throws SQLException
- * if a database access error occurs
- * @since 1.6
- */
- protected PreparedStatement prepareStatement(final Connection conn, final String sql, final int returnedKeys)
- throws SQLException {
-
- @SuppressWarnings("resource")
- final
- PreparedStatement ps = conn.prepareStatement(sql, returnedKeys);
- try {
- configureStatement(ps);
- } catch (final SQLException e) {
- ps.close();
- throw e;
- }
- return ps;
- }
-
- /**
- * Throws a new exception with a more informative error message.
- *
- * @param cause
- * The original exception that will be chained to the new
- * exception when it's rethrown.
- *
- * @param sql
- * The query that was executing when the exception happened.
- *
- * @param params
- * The query replacement parameters; {@code null} is a valid
- * value to pass in.
- *
- * @throws SQLException
- * if a database access error occurs
- */
- protected void rethrow(final SQLException cause, final String sql, final Object... params)
- throws SQLException {
-
- String causeMessage = cause.getMessage();
- if (causeMessage == null) {
- causeMessage = "";
- }
- final StringBuilder msg = new StringBuilder(causeMessage);
-
- msg.append(" Query: ");
- msg.append(sql);
- msg.append(" Parameters: ");
-
- if (params == null) {
- msg.append("[]");
- } else {
- msg.append(Arrays.deepToString(params));
- }
-
- final SQLException e = new SQLException(msg.toString(), cause.getSQLState(),
- cause.getErrorCode());
- e.setNextException(cause);
-
- throw e;
- }
-
- /**
- * Wrap the {@code ResultSet} in a decorator before processing it. This
- * implementation returns the {@code ResultSet} it is given without any
- * decoration.
- *
- * <p>
- * Often, the implementation of this method can be done in an anonymous
- * inner class like this:
- * </p>
- *
- * <pre>
- * QueryRunner run = new QueryRunner() {
- * protected ResultSet wrap(ResultSet rs) {
- * return StringTrimmedResultSet.wrap(rs);
- * }
- * };
- * </pre>
- *
- * @param rs
- * The {@code ResultSet} to decorate; never
- * {@code null}.
- * @return The {@code ResultSet} wrapped in some decorator.
- */
- protected ResultSet wrap(final ResultSet rs) {
- return rs;
- }
-
-}
+/*
+ * 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.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.ParameterMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.sql.Statement;
+import java.sql.Types;
+import java.util.Arrays;
+
+import javax.sql.DataSource;
+
+/**
+ * The base class for QueryRunner & AsyncQueryRunner. This class is thread safe.
+ *
+ * @since 1.4 (mostly extracted from QueryRunner)
+ */
+public abstract class AbstractQueryRunner {
+ /**
+ * Is {@link ParameterMetaData#getParameterType(int)} broken (have we tried
+ * it yet)?
+ */
+ private volatile boolean pmdKnownBroken = false;
+
+ /**
+ * The DataSource to retrieve connections from.
+ * @deprecated Access to this field should be through {@link #getDataSource()}.
+ */
+ @Deprecated
+ protected final DataSource ds;
+
+ /**
+ * Configuration to use when preparing statements.
+ */
+ private final StatementConfiguration stmtConfig;
+
+ /**
+ * Default constructor, sets pmdKnownBroken to false, ds to null and stmtConfig to null.
+ */
+ public AbstractQueryRunner() {
+ ds = null;
+ this.stmtConfig = null;
+ }
+
+ /**
+ * Constructor to control the use of {@code ParameterMetaData}.
+ *
+ * @param pmdKnownBroken
+ * Some drivers don't support
+ * {@link 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 AbstractQueryRunner(final boolean pmdKnownBroken) {
+ this.pmdKnownBroken = pmdKnownBroken;
+ ds = null;
+ this.stmtConfig = null;
+ }
+
+ /**
+ * Constructor to provide a {@code DataSource}. 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 AbstractQueryRunner(final DataSource ds) {
+ this.ds = ds;
+ this.stmtConfig = null;
+ }
+
+ /**
+ * Constructor to provide a {@code DataSource} and control 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 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 AbstractQueryRunner(final DataSource ds, final boolean pmdKnownBroken) {
+ this.pmdKnownBroken = pmdKnownBroken;
+ this.ds = ds;
+ this.stmtConfig = null;
+ }
+
+ /**
+ * 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 AbstractQueryRunner(final DataSource ds, final boolean pmdKnownBroken, final StatementConfiguration stmtConfig) {
+ this.pmdKnownBroken = pmdKnownBroken;
+ this.ds = ds;
+ this.stmtConfig = stmtConfig;
+ }
+
+ /**
+ * 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 AbstractQueryRunner(final DataSource ds, final StatementConfiguration stmtConfig) {
+ this.ds = ds;
+ this.stmtConfig = stmtConfig;
+ }
+
+ /**
+ * 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 AbstractQueryRunner(final StatementConfiguration stmtConfig) {
+ this.ds = null;
+ this.stmtConfig = stmtConfig;
+ }
+
+ /**
+ * Close a {@code Connection}. This implementation avoids closing if
+ * null and does <strong>not</strong> suppress any exceptions. Subclasses
+ * can override to provide special handling like logging.
+ *
+ * @param conn
+ * Connection to close
+ * @throws SQLException
+ * if a database access error occurs
+ * @since 1.1
+ */
+ protected void close(final Connection conn) throws SQLException {
+ DbUtils.close(conn);
+ }
+
+ /**
+ * Close a {@code ResultSet}. This implementation avoids closing if
+ * null and does <strong>not</strong> suppress any exceptions. Subclasses
+ * can override to provide special handling like logging.
+ *
+ * @param rs
+ * ResultSet to close
+ * @throws SQLException
+ * if a database access error occurs
+ * @since 1.1
+ */
+ protected void close(final ResultSet rs) throws SQLException {
+ DbUtils.close(rs);
+ }
+
+ /**
+ * Close a {@code Statement}. This implementation avoids closing if
+ * null and does <strong>not</strong> suppress any exceptions. Subclasses
+ * can override to provide special handling like logging.
+ *
+ * @param stmt
+ * Statement to close
+ * @throws SQLException
+ * if a database access error occurs
+ * @since 1.1
+ */
+ protected void close(final Statement stmt) throws SQLException {
+ DbUtils.close(stmt);
+ }
+
+ /**
+ * Calls {@link DbUtils#closeQuietly(Connection)}.
+ *
+ * @param conn Connection to close.
+ * @since 2.0
+ */
+ protected void closeQuietly(final Connection conn) {
+ DbUtils.closeQuietly(conn);
+ }
+
+ /**
+ * Calls {@link DbUtils#closeQuietly(ResultSet)}.
+ *
+ * @param rs ResultSet to close.
+ * @since 2.0
+ */
+ protected void closeQuietly(final ResultSet rs) {
+ DbUtils.closeQuietly(rs);
+ }
+
+ /**
+ * Calls {@link DbUtils#closeQuietly(Statement)}.
+ *
+ * @param statement ResultSet to close.
+ * @since 2.0
+ */
+ protected void closeQuietly(final Statement statement) {
+ DbUtils.closeQuietly(statement);
+ }
+
+ private void configureStatement(final Statement stmt) throws SQLException {
+
+ if (stmtConfig != null) {
+ if (stmtConfig.isFetchDirectionSet()) {
+ stmt.setFetchDirection(stmtConfig.getFetchDirection());
+ }
+
+ if (stmtConfig.isFetchSizeSet()) {
+ stmt.setFetchSize(stmtConfig.getFetchSize());
+ }
+
+ if (stmtConfig.isMaxFieldSizeSet()) {
+ stmt.setMaxFieldSize(stmtConfig.getMaxFieldSize());
+ }
+
+ if (stmtConfig.isMaxRowsSet()) {
+ stmt.setMaxRows(stmtConfig.getMaxRows());
+ }
+
+ if (stmtConfig.isQueryTimeoutSet()) {
+ stmt.setQueryTimeout(stmtConfig.getQueryTimeout());
+ }
+ }
+ }
+
+ /**
+ * Fill the {@code PreparedStatement} replacement parameters with the
+ * given objects.
+ *
+ * @param stmt
+ * PreparedStatement to fill
+ * @param params
+ * Query replacement parameters; {@code null} is a valid
+ * value to pass in.
+ * @throws SQLException
+ * if a database access error occurs
+ */
+ public void fillStatement(final PreparedStatement stmt, final Object... params)
+ throws SQLException {
+
+ // check the parameter count, if we can
+ ParameterMetaData pmd = null;
+ if (!pmdKnownBroken) {
+ try {
+ pmd = stmt.getParameterMetaData();
+ if (pmd == null) { // can be returned by implementations that don't support the method
+ pmdKnownBroken = true;
+ } else {
+ final int stmtCount = pmd.getParameterCount();
+ final int paramsCount = params == null ? 0 : params.length;
+
+ if (stmtCount != paramsCount) {
+ throw new SQLException("Wrong number of parameters: expected "
+ + stmtCount + ", was given " + paramsCount);
+ }
+ }
+ } catch (final SQLFeatureNotSupportedException ex) {
+ pmdKnownBroken = true;
+ }
+ // TODO see DBUTILS-117: would it make sense to catch any other SQLEx types here?
+ }
+
+ // nothing to do here
+ if (params == null) {
+ return;
+ }
+
+ CallableStatement call = null;
+ if (stmt instanceof CallableStatement) {
+ call = (CallableStatement) stmt;
+ }
+
+ for (int i = 0; i < params.length; i++) {
+ if (params[i] != null) {
+ if (call != null && params[i] instanceof OutParameter) {
+ ((OutParameter)params[i]).register(call, i + 1);
+ } else {
+ stmt.setObject(i + 1, params[i]);
+ }
+ } else {
+ // VARCHAR works with many drivers regardless
+ // of the actual column type. Oddly, NULL and
+ // OTHER don't work with Oracle's drivers.
+ int sqlType = Types.VARCHAR;
+ if (!pmdKnownBroken) {
+ // TODO see DBUTILS-117: does it make sense to catch SQLEx here?
+ try {
+ /*
+ * It's not possible for pmdKnownBroken to change from
+ * true to false, (once true, always true) so pmd cannot
+ * be null here.
+ */
+ sqlType = pmd.getParameterType(i + 1);
+ } catch (final SQLException e) {
+ pmdKnownBroken = true;
+ }
+ }
+ stmt.setNull(i + 1, sqlType);
+ }
+ }
+ }
+
+ /**
+ * Fill the {@code PreparedStatement} replacement parameters with the
+ * given object's bean property values.
+ *
+ * @param stmt
+ * PreparedStatement to fill
+ * @param bean
+ * a JavaBean object
+ * @param properties
+ * an ordered array of properties; this gives the order to insert
+ * values in the statement
+ * @throws SQLException
+ * if a database access error occurs
+ */
+ public void fillStatementWithBean(final PreparedStatement stmt, final Object bean,
+ final PropertyDescriptor[] properties) throws SQLException {
+ final Object[] params = new Object[properties.length];
+ for (int i = 0; i < properties.length; i++) {
+ final PropertyDescriptor property = properties[i];
+ Object value = null;
+ final Method method = property.getReadMethod();
+ if (method == null) {
+ throw new RuntimeException("No read method for bean property "
+ + bean.getClass() + " " + property.getName());
+ }
+ try {
+ value = method.invoke(bean);
+ } catch (final IllegalArgumentException e) {
+ throw new RuntimeException(
+ "Couldn't invoke method with 0 arguments: " + method, e);
+ } catch (final InvocationTargetException | IllegalAccessException e) {
+ throw new RuntimeException("Couldn't invoke method: " + method,
+ e);
+ }
+ params[i] = value;
+ }
+ fillStatement(stmt, params);
+ }
+
+ /**
+ * Fill the {@code PreparedStatement} replacement parameters with the
+ * given object's bean property values.
+ *
+ * @param stmt
+ * PreparedStatement to fill
+ * @param bean
+ * A JavaBean object
+ * @param propertyNames
+ * An ordered array of property names (these should match the
+ * getters/setters); this gives the order to insert values in the
+ * statement
+ * @throws SQLException
+ * If a database access error occurs
+ */
+ public void fillStatementWithBean(final PreparedStatement stmt, final Object bean,
+ final String... propertyNames) throws SQLException {
+ PropertyDescriptor[] descriptors;
+ try {
+ descriptors = Introspector.getBeanInfo(bean.getClass())
+ .getPropertyDescriptors();
+ } catch (final IntrospectionException e) {
+ throw new RuntimeException("Couldn't introspect bean "
+ + bean.getClass().toString(), e);
+ }
+ final PropertyDescriptor[] sorted = new PropertyDescriptor[propertyNames.length];
+ for (int i = 0; i < propertyNames.length; i++) {
+ final String propertyName = propertyNames[i];
+ if (propertyName == null) {
+ throw new NullPointerException("propertyName can't be null: "
+ + i);
+ }
+ boolean found = false;
+ for (final PropertyDescriptor descriptor : descriptors) {
+ if (propertyName.equals(descriptor.getName())) {
+ sorted[i] = descriptor;
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ throw new RuntimeException("Couldn't find bean property: "
+ + bean.getClass() + " " + propertyName);
+ }
+ }
+ fillStatementWithBean(stmt, bean, sorted);
+ }
+
+ /**
+ * Returns the {@code DataSource} this runner is using.
+ * {@code QueryRunner} methods always call this method to get the
+ * {@code DataSource} so subclasses can provide specialized behavior.
+ *
+ * @return DataSource the runner is using
+ */
+ public DataSource getDataSource() {
+ return this.ds;
+ }
+
+ /**
+ * Some drivers don't support
+ * {@link 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.
+ *
+ * @return the flag to skip (or not)
+ * {@link ParameterMetaData#getParameterType(int) }
+ * @since 1.4
+ */
+ public boolean isPmdKnownBroken() {
+ return pmdKnownBroken;
+ }
+
+ /**
+ * Factory method that creates and initializes a
+ * {@code CallableStatement} object for the given SQL.
+ * {@code QueryRunner} methods always call this method to prepare
+ * callable statements for them. Subclasses can override this method to
+ * provide special CallableStatement configuration if needed. This
+ * implementation simply calls {@code conn.prepareCall(sql)}.
+ *
+ * @param conn
+ * The {@code Connection} used to create the
+ * {@code CallableStatement}
+ * @param sql
+ * The SQL statement to prepare.
+ * @return An initialized {@code CallableStatement}.
+ * @throws SQLException
+ * if a database access error occurs
+ */
+ protected CallableStatement prepareCall(final Connection conn, final String sql)
+ throws SQLException {
+
+ return conn.prepareCall(sql);
+ }
+
+ /**
+ * Factory method that creates and initializes a {@code Connection}
+ * object. {@code QueryRunner} methods always call this method to
+ * retrieve connections from its DataSource. Subclasses can override this
+ * method to provide special {@code Connection} configuration if
+ * needed. This implementation simply calls {@code ds.getConnection()}.
+ *
+ * @return An initialized {@code Connection}.
+ * @throws SQLException
+ * if a database access error occurs
+ * @since 1.1
+ */
+ protected Connection prepareConnection() throws SQLException {
+ if (this.getDataSource() == null) {
+ throw new SQLException(
+ "QueryRunner requires a DataSource to be "
+ + "invoked in this way, or a Connection should be passed in");
+ }
+ return this.getDataSource().getConnection();
+ }
+
+ /**
+ * Factory method that creates and initializes a
+ * {@code PreparedStatement} object for the given SQL.
+ * {@code QueryRunner} methods always call this method to prepare
+ * statements for them. Subclasses can override this method to provide
+ * special PreparedStatement configuration if needed. This implementation
+ * simply calls {@code conn.prepareStatement(sql)}.
+ *
+ * @param conn
+ * The {@code Connection} used to create the
+ * {@code PreparedStatement}
+ * @param sql
+ * The SQL statement to prepare.
+ * @return An initialized {@code PreparedStatement}.
+ * @throws SQLException
+ * if a database access error occurs
+ */
+ protected PreparedStatement prepareStatement(final Connection conn, final String sql)
+ throws SQLException {
+
+ @SuppressWarnings("resource")
+ final
+ PreparedStatement ps = conn.prepareStatement(sql);
+ try {
+ configureStatement(ps);
+ } catch (final SQLException e) {
+ ps.close();
+ throw e;
+ }
+ return ps;
+ }
+
+ /**
+ * Factory method that creates and initializes a
+ * {@code PreparedStatement} object for the given SQL.
+ * {@code QueryRunner} methods always call this method to prepare
+ * statements for them. Subclasses can override this method to provide
+ * special PreparedStatement configuration if needed. This implementation
+ * simply calls {@code conn.prepareStatement(sql, returnedKeys)}
+ * which will result in the ability to retrieve the automatically-generated
+ * keys from an auto_increment column.
+ *
+ * @param conn
+ * The {@code Connection} used to create the
+ * {@code PreparedStatement}
+ * @param sql
+ * The SQL statement to prepare.
+ * @param returnedKeys
+ * Flag indicating whether to return generated keys or not.
+ *
+ * @return An initialized {@code PreparedStatement}.
+ * @throws SQLException
+ * if a database access error occurs
+ * @since 1.6
+ */
+ protected PreparedStatement prepareStatement(final Connection conn, final String sql, final int returnedKeys)
+ throws SQLException {
+
+ @SuppressWarnings("resource")
+ final
+ PreparedStatement ps = conn.prepareStatement(sql, returnedKeys);
+ try {
+ configureStatement(ps);
+ } catch (final SQLException e) {
+ ps.close();
+ throw e;
+ }
+ return ps;
+ }
+
+ /**
+ * Throws a new exception with a more informative error message.
+ *
+ * @param cause
+ * The original exception that will be chained to the new
+ * exception when it's rethrown.
+ *
+ * @param sql
+ * The query that was executing when the exception happened.
+ *
+ * @param params
+ * The query replacement parameters; {@code null} is a valid
+ * value to pass in.
+ *
+ * @throws SQLException
+ * if a database access error occurs
+ */
+ protected void rethrow(final SQLException cause, final String sql, final Object... params)
+ throws SQLException {
+
+ String causeMessage = cause.getMessage();
+ if (causeMessage == null) {
+ causeMessage = "";
+ }
+ final StringBuilder msg = new StringBuilder(causeMessage);
+
+ msg.append(" Query: ");
+ msg.append(sql);
+ msg.append(" Parameters: ");
+
+ if (params == null) {
+ msg.append("[]");
+ } else {
+ msg.append(Arrays.deepToString(params));
+ }
+
+ final SQLException e = new SQLException(msg.toString(), cause.getSQLState(),
+ cause.getErrorCode());
+ e.setNextException(cause);
+
+ throw e;
+ }
+
+ /**
+ * Wrap the {@code ResultSet} in a decorator before processing it. This
+ * implementation returns the {@code ResultSet} it is given without any
+ * decoration.
+ *
+ * <p>
+ * Often, the implementation of this method can be done in an anonymous
+ * inner class like this:
+ * </p>
+ *
+ * <pre>
+ * QueryRunner run = new QueryRunner() {
+ * protected ResultSet wrap(ResultSet rs) {
+ * return StringTrimmedResultSet.wrap(rs);
+ * }
+ * };
+ * </pre>
+ *
+ * @param rs
+ * The {@code ResultSet} to decorate; never
+ * {@code null}.
+ * @return The {@code ResultSet} wrapped in some decorator.
+ */
+ protected ResultSet wrap(final ResultSet rs) {
+ return rs;
+ }
+
+}
diff --git a/src/main/java/org/apache/commons/dbutils/AsyncQueryRunner.java b/src/main/java/org/apache/commons/dbutils/AsyncQueryRunner.java
index f430a28..c9aaa67 100644
--- a/src/main/java/org/apache/commons/dbutils/AsyncQueryRunner.java
+++ b/src/main/java/org/apache/commons/dbutils/AsyncQueryRunner.java
@@ -1,691 +1,691 @@
-/*
- * 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.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-
-import javax.sql.DataSource;
-
-/**
- * Executes SQL queries with pluggable strategies for handling
- * {@code ResultSet}s. This class is thread safe.
- *
- * @see ResultSetHandler
- * @since 1.4
- */
-public class AsyncQueryRunner extends AbstractQueryRunner {
-
- private final ExecutorService executorService;
- private final QueryRunner queryRunner;
-
- /**
- * Constructor for AsyncQueryRunner which uses a provided ExecutorService and underlying QueryRunner.
- *
- * @param executorService the {@code ExecutorService} instance used to run JDBC invocations concurrently.
- * @param queryRunner the {@code QueryRunner} instance to use for the queries.
- * @since DbUtils 1.5
- */
- public AsyncQueryRunner(final ExecutorService executorService, final QueryRunner queryRunner) {
- this.executorService = executorService;
- this.queryRunner = queryRunner;
- }
-
- /**
- * Constructor for AsyncQueryRunner.
- *
- * @param executorService the {@code ExecutorService} instance used to run JDBC invocations concurrently.
- */
- public AsyncQueryRunner(final ExecutorService executorService) {
- this(null, false, executorService);
- }
-
- /**
- * @deprecated Use {@link #AsyncQueryRunner(ExecutorService, QueryRunner)} instead.
- * Constructor for AsyncQueryRunner 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.
- * @param executorService the {@code ExecutorService} instance used to run JDBC invocations concurrently.
- */
- @Deprecated
- public AsyncQueryRunner(final boolean pmdKnownBroken, final ExecutorService executorService) {
- this(null, pmdKnownBroken, executorService);
- }
-
- /**
- * @deprecated Use {@link #AsyncQueryRunner(ExecutorService, QueryRunner)} instead.
- * Constructor for AsyncQueryRunner that takes a {@code DataSource}.
- *
- * 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 executorService the {@code ExecutorService} instance used to run JDBC invocations concurrently.
- */
- @Deprecated
- public AsyncQueryRunner(final DataSource ds, final ExecutorService executorService) {
- this(ds, false, executorService);
- }
-
- /**
- * @deprecated Use {@link #AsyncQueryRunner(ExecutorService, QueryRunner)} instead.
- * Constructor for AsyncQueryRunner that take 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.
- * @param executorService the {@code ExecutorService} instance used to run JDBC invocations concurrently.
- */
- @Deprecated
- public AsyncQueryRunner(final DataSource ds, final boolean pmdKnownBroken, final ExecutorService executorService) {
- super(ds, pmdKnownBroken);
- this.executorService = executorService;
- this.queryRunner = new QueryRunner(ds, pmdKnownBroken);
- }
-
- /**
- * @deprecated No longer used by this class. Will be removed in a future version.
- * Class that encapsulates the continuation for batch calls.
- */
- @Deprecated
- protected class BatchCallableStatement implements Callable<int[]> {
- private final String sql;
- private final Object[][] params;
- private final Connection conn;
- private final boolean closeConn;
- private final PreparedStatement ps;
-
- /**
- * Creates a new BatchCallableStatement instance.
- *
- * @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.
- * @param conn The connection to use for the batch call.
- * @param closeConn True if the connection should be closed, false otherwise.
- * @param ps The {@link PreparedStatement} to be executed.
- */
- public BatchCallableStatement(final String sql, final Object[][] params, final Connection conn, final boolean closeConn, final PreparedStatement ps) {
- this.sql = sql;
- this.params = params.clone();
- this.conn = conn;
- this.closeConn = closeConn;
- this.ps = ps;
- }
-
- /**
- * The actual call to executeBatch.
- *
- * @return an array of update counts containing one element for each command in the batch.
- * @throws SQLException if a database access error occurs or one of the commands sent to the database fails.
- * @see PreparedStatement#executeBatch()
- */
- @Override
- public int[] call() throws SQLException {
- int[] ret = null;
-
- try {
- ret = ps.executeBatch();
- } catch (final SQLException e) {
- rethrow(e, sql, (Object[])params);
- } finally {
- close(ps);
- if (closeConn) {
- close(conn);
- }
- }
-
- return ret;
- }
- }
-
- /**
- * Execute a batch of SQL INSERT, UPDATE, or DELETE queries.
- *
- * @param conn The {@code 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 A {@code Future} which returns the number of rows updated per statement.
- * @throws SQLException if a database access error occurs
- */
- public Future<int[]> batch(final Connection conn, final String sql, final Object[][] params) throws SQLException {
- return executorService.submit(new Callable<int[]>() {
-
- @Override
- public int[] call() throws Exception {
- return queryRunner.batch(conn, sql, params);
- }
-
- });
- }
-
- /**
- * 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 A {@code Future} which returns the number of rows updated per statement.
- * @throws SQLException if a database access error occurs
- */
- public Future<int[]> batch(final String sql, final Object[][] params) throws SQLException {
- return executorService.submit(new Callable<int[]>() {
-
- @Override
- public int[] call() throws Exception {
- return queryRunner.batch(sql, params);
- }
-
- });
- }
-
- /**
- * Class that encapsulates the continuation for query calls.
- * @param <T> The type of the result from the call to handle.
- */
- protected class QueryCallableStatement<T> implements Callable<T> {
- private final String sql;
- private final Object[] params;
- private final Connection conn;
- private final boolean closeConn;
- private final PreparedStatement ps;
- private final ResultSetHandler<T> rsh;
-
- /**
- * Creates a new {@code QueryCallableStatement} instance.
- *
- * @param conn The connection to use for the batch call.
- * @param closeConn True if the connection should be closed, false otherwise.
- * @param ps The {@link PreparedStatement} to be executed.
- * @param rsh The handler that converts the results into an object.
- * @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.
- */
- public QueryCallableStatement(final Connection conn, final boolean closeConn, final PreparedStatement ps,
- final ResultSetHandler<T> rsh, final String sql, final Object... params) {
- this.sql = sql;
- this.params = params;
- this.conn = conn;
- this.closeConn = closeConn;
- this.ps = ps;
- this.rsh = rsh;
- }
-
- /**
- * The actual call to {@code handle()} method.
- *
- * @return an array of update counts containing one element for each command in the batch.
- * @throws SQLException if a database access error occurs.
- * @see ResultSetHandler#handle(ResultSet)
- */
- @Override
- public T call() throws SQLException {
- ResultSet rs = null;
- T ret = null;
-
- try {
- rs = wrap(ps.executeQuery());
- ret = rsh.handle(rs);
- } catch (final SQLException e) {
- rethrow(e, sql, params);
- } finally {
- try {
- close(rs);
- } finally {
- close(ps);
- if (closeConn) {
- close(conn);
- }
- }
- }
-
- return ret;
- }
-
- }
-
- /**
- * Execute an SQL SELECT query with replacement parameters. The
- * caller is responsible for closing the connection.
- * @param <T> The type of object that the handler returns
- * @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 A {@code Future} which returns the result of the query call.
- * @throws SQLException if a database access error occurs
- */
- public <T> Future<T> query(final Connection conn, final String sql, final ResultSetHandler<T> rsh, final Object... params)
- throws SQLException {
- return executorService.submit(new Callable<T>() {
-
- @Override
- public T call() throws Exception {
- return queryRunner.query(conn, sql, rsh, params);
- }
-
- });
- }
-
- /**
- * 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 A {@code Future} which returns the result of the query call.
- * @throws SQLException if a database access error occurs
- */
- public <T> Future<T> query(final Connection conn, final String sql, final ResultSetHandler<T> rsh) throws SQLException {
- return executorService.submit(new Callable<T>() {
-
- @Override
- public T call() throws Exception {
- return queryRunner.query(conn, sql, rsh);
- }
-
- });
- }
-
- /**
- * 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 A {@code Future} which returns the result of the query call.
- * @throws SQLException if a database access error occurs
- */
- public <T> Future<T> query(final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
- return executorService.submit(new Callable<T>() {
-
- @Override
- public T call() throws Exception {
- return queryRunner.query(sql, rsh, params);
- }
-
- });
- }
-
- /**
- * 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 A {@code Future} which returns the result of the query call.
- * @throws SQLException if a database access error occurs
- */
- public <T> Future<T> query(final String sql, final ResultSetHandler<T> rsh) throws SQLException {
- return executorService.submit(new Callable<T>() {
-
- @Override
- public T call() throws Exception {
- return queryRunner.query(sql, rsh);
- }
-
- });
- }
-
- /**
- * @deprecated No longer used by this class. Will be removed in a future version.
- * Class that encapsulates the continuation for update calls.
- */
- @Deprecated
- protected class UpdateCallableStatement implements Callable<Integer> {
- private final String sql;
- private final Object[] params;
- private final Connection conn;
- private final boolean closeConn;
- private final PreparedStatement ps;
-
- /**
- *
- *
- * @param conn The connection to use for the batch call.
- * @param closeConn True if the connection should be closed, false otherwise.
- * @param ps The {@link PreparedStatement} to be executed.
- * @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.
- */
- public UpdateCallableStatement(final Connection conn, final boolean closeConn, final PreparedStatement ps, final String sql, final Object... params) {
- this.sql = sql;
- this.params = params;
- this.conn = conn;
- this.closeConn = closeConn;
- this.ps = ps;
- }
-
- /**
- * The actual call to {@code executeUpdate()} method.
- *
- * @return either (1) the row count for SQL Data Manipulation Language (DML) statements or
- * (2) 0 for SQL statements that return nothing
- * @throws SQLException if a database access error occurs.
- * @see PreparedStatement#executeUpdate()
- */
- @Override
- public Integer call() throws SQLException {
- int rows = 0;
-
- try {
- rows = ps.executeUpdate();
- } catch (final SQLException e) {
- rethrow(e, sql, params);
- } finally {
- close(ps);
- if (closeConn) {
- close(conn);
- }
- }
-
- return Integer.valueOf(rows);
- }
-
- }
-
- /**
- * 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 A {@code Future} which returns the number of rows updated.
- * @throws SQLException if a database access error occurs
- */
- public Future<Integer> update(final Connection conn, final String sql) throws SQLException {
- return executorService.submit(new Callable<Integer>() {
-
- @Override
- public Integer call() throws Exception {
- return Integer.valueOf(queryRunner.update(conn, sql));
- }
-
- });
- }
-
- /**
- * 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 A {@code Future} which returns the number of rows updated.
- * @throws SQLException if a database access error occurs
- */
- public Future<Integer> update(final Connection conn, final String sql, final Object param) throws SQLException {
- return executorService.submit(new Callable<Integer>() {
-
- @Override
- public Integer call() throws Exception {
- return Integer.valueOf(queryRunner.update(conn, 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 A {@code Future} which returns the number of rows updated.
- * @throws SQLException if a database access error occurs
- */
- public Future<Integer> update(final Connection conn, final String sql, final Object... params) throws SQLException {
- return executorService.submit(new Callable<Integer>() {
-
- @Override
- public Integer call() throws Exception {
- return Integer.valueOf(queryRunner.update(conn, 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 A {@code Future} which returns the number of rows updated.
- */
- public Future<Integer> update(final String sql) throws SQLException {
- return executorService.submit(new Callable<Integer>() {
-
- @Override
- public Integer call() throws Exception {
- return Integer.valueOf(queryRunner.update(sql));
- }
-
- });
- }
-
- /**
- * 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 A {@code Future} which returns the number of rows updated.
- */
- public Future<Integer> update(final String sql, final Object param) throws SQLException {
- return executorService.submit(new Callable<Integer>() {
-
- @Override
- public Integer call() throws Exception {
- return Integer.valueOf(queryRunner.update(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 A {@code Future} which returns the number of rows updated.
- */
- public Future<Integer> update(final String sql, final Object... params) throws SQLException {
- return executorService.submit(new Callable<Integer>() {
-
- @Override
- public Integer call() throws Exception {
- return Integer.valueOf(queryRunner.update(sql, params));
- }
-
- });
- }
-
- /**
- * Executes {@link QueryRunner#insert(String, ResultSetHandler)} asynchronously.
- *
- * @param <T> Return type expected
- * @param sql SQL insert statement to execute
- * @param rsh {@link ResultSetHandler} for handling the results
- * @return {@link Future} that executes a query runner insert
- * @see QueryRunner#insert(String, ResultSetHandler)
- * @throws SQLException if a database access error occurs
- * @since 1.6
- */
- public <T> Future<T> insert(final String sql, final ResultSetHandler<T> rsh) throws SQLException {
- return executorService.submit(new Callable<T>() {
-
- @Override
- public T call() throws Exception {
- return queryRunner.insert(sql, rsh);
- }
-
- });
- }
-
- /**
- * Executes {@link QueryRunner#insert(String, ResultSetHandler, Object...)} asynchronously.
- *
- * @param <T> Return type expected
- * @param sql SQL insert statement to execute
- * @param rsh {@link ResultSetHandler} for handling the results
- * @param params Parameter values for substitution in the SQL statement
- * @return {@link Future} that executes a query runner insert
- * @see QueryRunner#insert(String, ResultSetHandler, Object...)
- * @throws SQLException if a database access error occurs
- * @since 1.6
- */
- public <T> Future<T> insert(final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
- return executorService.submit(new Callable<T>() {
-
- @Override
- public T call() throws Exception {
- return queryRunner.insert(sql, rsh, params);
- }
- });
- }
-
- /**
- * Executes {@link QueryRunner#insert(Connection, String, ResultSetHandler)} asynchronously.
- *
- * @param <T> Return type expected
- * @param conn {@link Connection} to use to execute the SQL statement
- * @param sql SQL insert statement to execute
- * @param rsh {@link ResultSetHandler} for handling the results
- * @return {@link Future} that executes a query runner insert
- * @see QueryRunner#insert(Connection, String, ResultSetHandler)
- * @throws SQLException if a database access error occurs
- * @since 1.6
- */
- public <T> Future<T> insert(final Connection conn, final String sql, final ResultSetHandler<T> rsh) throws SQLException {
- return executorService.submit(new Callable<T>() {
-
- @Override
- public T call() throws Exception {
- return queryRunner.insert(conn, sql, rsh);
- }
- });
- }
-
- /**
- * Executes {@link QueryRunner#insert(Connection, String, ResultSetHandler, Object...)} asynchronously.
- *
- * @param <T> Return type expected
- * @param conn {@link Connection} to use to execute the SQL statement
- * @param sql SQL insert statement to execute
- * @param rsh {@link ResultSetHandler} for handling the results
- * @param params Parameter values for substitution in the SQL statement
- * @return {@link Future} that executes a query runner insert
- * @see QueryRunner#insert(Connection, String, ResultSetHandler, Object...)
- * @throws SQLException if a database access error occurs
- * @since 1.6
- */
- public <T> Future<T> insert(final Connection conn, final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
- return executorService.submit(new Callable<T>() {
-
- @Override
- public T call() throws Exception {
- return queryRunner.insert(conn, sql, rsh, params);
- }
- });
- }
-
- /**
- * {@link QueryRunner#insertBatch(String, ResultSetHandler, Object[][])} asynchronously.
- *
- * @param <T> Return type expected
- * @param sql SQL insert statement to execute
- * @param rsh {@link ResultSetHandler} for handling the results
- * @param params An array of query replacement parameters. Each row in
- * this array is one set of batch replacement values.
- * @return {@link Future} that executes a query runner batch insert
- * @see QueryRunner#insertBatch(String, ResultSetHandler, Object[][])
- * @throws SQLException if a database access error occurs
- * @since 1.6
- */
- public <T> Future<T> insertBatch(final String sql, final ResultSetHandler<T> rsh, final Object[][] params) throws SQLException {
- return executorService.submit(new Callable<T>() {
-
- @Override
- public T call() throws Exception {
- return queryRunner.insertBatch(sql, rsh, params);
- }
- });
- }
-
- /**
- * {@link QueryRunner#insertBatch(Connection, String, ResultSetHandler, Object[][])} asynchronously.
- *
- * @param <T> Return type expected
- * @param conn {@link Connection} to use to execute the SQL statement
- * @param sql SQL insert statement to execute
- * @param rsh {@link ResultSetHandler} for handling the results
- * @param params An array of query replacement parameters. Each row in
- * this array is one set of batch replacement values.
- * @return {@link Future} that executes a query runner batch insert
- * @see QueryRunner#insertBatch(Connection, String, ResultSetHandler, Object[][])
- * @throws SQLException if a database access error occurs
- * @since 1.6
- */
- public <T> Future<T> insertBatch(final Connection conn, final String sql, final ResultSetHandler<T> rsh, final Object[][] params) throws SQLException {
- return executorService.submit(new Callable<T>() {
-
- @Override
- public T call() throws Exception {
- return queryRunner.insertBatch(conn, sql, rsh, params);
- }
- });
- }
-
-}
+/*
+ * 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.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+import javax.sql.DataSource;
+
+/**
+ * Executes SQL queries with pluggable strategies for handling
+ * {@code ResultSet}s. This class is thread safe.
+ *
+ * @see ResultSetHandler
+ * @since 1.4
+ */
+public class AsyncQueryRunner extends AbstractQueryRunner {
+
+ private final ExecutorService executorService;
+ private final QueryRunner queryRunner;
+
+ /**
+ * Constructor for AsyncQueryRunner which uses a provided ExecutorService and underlying QueryRunner.
+ *
+ * @param executorService the {@code ExecutorService} instance used to run JDBC invocations concurrently.
+ * @param queryRunner the {@code QueryRunner} instance to use for the queries.
+ * @since 1.5
+ */
+ public AsyncQueryRunner(final ExecutorService executorService, final QueryRunner queryRunner) {
+ this.executorService = executorService;
+ this.queryRunner = queryRunner;
+ }
+
+ /**
+ * Constructor for AsyncQueryRunner.
+ *
+ * @param executorService the {@code ExecutorService} instance used to run JDBC invocations concurrently.
+ */
+ public AsyncQueryRunner(final ExecutorService executorService) {
+ this(null, false, executorService);
+ }
+
+ /**
+ * @deprecated Use {@link #AsyncQueryRunner(ExecutorService, QueryRunner)} instead.
+ * Constructor for AsyncQueryRunner 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.
+ * @param executorService the {@code ExecutorService} instance used to run JDBC invocations concurrently.
+ */
+ @Deprecated
+ public AsyncQueryRunner(final boolean pmdKnownBroken, final ExecutorService executorService) {
+ this(null, pmdKnownBroken, executorService);
+ }
+
+ /**
+ * @deprecated Use {@link #AsyncQueryRunner(ExecutorService, QueryRunner)} instead.
+ * Constructor for AsyncQueryRunner that takes a {@code DataSource}.
+ *
+ * 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 executorService the {@code ExecutorService} instance used to run JDBC invocations concurrently.
+ */
+ @Deprecated
+ public AsyncQueryRunner(final DataSource ds, final ExecutorService executorService) {
+ this(ds, false, executorService);
+ }
+
+ /**
+ * @deprecated Use {@link #AsyncQueryRunner(ExecutorService, QueryRunner)} instead.
+ * Constructor for AsyncQueryRunner that take 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.
+ * @param executorService the {@code ExecutorService} instance used to run JDBC invocations concurrently.
+ */
+ @Deprecated
+ public AsyncQueryRunner(final DataSource ds, final boolean pmdKnownBroken, final ExecutorService executorService) {
+ super(ds, pmdKnownBroken);
+ this.executorService = executorService;
+ this.queryRunner = new QueryRunner(ds, pmdKnownBroken);
+ }
+
+ /**
+ * @deprecated No longer used by this class. Will be removed in a future version.
+ * Class that encapsulates the continuation for batch calls.
+ */
+ @Deprecated
+ protected class BatchCallableStatement implements Callable<int[]> {
+ private final String sql;
+ private final Object[][] params;
+ private final Connection conn;
+ private final boolean closeConn;
+ private final PreparedStatement ps;
+
+ /**
+ * Creates a new BatchCallableStatement instance.
+ *
+ * @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.
+ * @param conn The connection to use for the batch call.
+ * @param closeConn True if the connection should be closed, false otherwise.
+ * @param ps The {@link PreparedStatement} to be executed.
+ */
+ public BatchCallableStatement(final String sql, final Object[][] params, final Connection conn, final boolean closeConn, final PreparedStatement ps) {
+ this.sql = sql;
+ this.params = params.clone();
+ this.conn = conn;
+ this.closeConn = closeConn;
+ this.ps = ps;
+ }
+
+ /**
+ * The actual call to executeBatch.
+ *
+ * @return an array of update counts containing one element for each command in the batch.
+ * @throws SQLException if a database access error occurs or one of the commands sent to the database fails.
+ * @see PreparedStatement#executeBatch()
+ */
+ @Override
+ public int[] call() throws SQLException {
+ int[] ret = null;
+
+ try {
+ ret = ps.executeBatch();
+ } catch (final SQLException e) {
+ rethrow(e, sql, (Object[])params);
+ } finally {
+ close(ps);
+ if (closeConn) {
+ close(conn);
+ }
+ }
+
+ return ret;
+ }
+ }
+
+ /**
+ * Execute a batch of SQL INSERT, UPDATE, or DELETE queries.
+ *
+ * @param conn The {@code 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 A {@code Future} which returns the number of rows updated per statement.
+ * @throws SQLException if a database access error occurs
+ */
+ public Future<int[]> batch(final Connection conn, final String sql, final Object[][] params) throws SQLException {
+ return executorService.submit(new Callable<int[]>() {
+
+ @Override
+ public int[] call() throws Exception {
+ return queryRunner.batch(conn, sql, params);
+ }
+
+ });
+ }
+
+ /**
+ * 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 A {@code Future} which returns the number of rows updated per statement.
+ * @throws SQLException if a database access error occurs
+ */
+ public Future<int[]> batch(final String sql, final Object[][] params) throws SQLException {
+ return executorService.submit(new Callable<int[]>() {
+
+ @Override
+ public int[] call() throws Exception {
+ return queryRunner.batch(sql, params);
+ }
+
+ });
+ }
+
+ /**
+ * Class that encapsulates the continuation for query calls.
+ * @param <T> The type of the result from the call to handle.
+ */
+ protected class QueryCallableStatement<T> implements Callable<T> {
+ private final String sql;
+ private final Object[] params;
+ private final Connection conn;
+ private final boolean closeConn;
+ private final PreparedStatement ps;
+ private final ResultSetHandler<T> rsh;
+
+ /**
+ * Creates a new {@code QueryCallableStatement} instance.
+ *
+ * @param conn The connection to use for the batch call.
+ * @param closeConn True if the connection should be closed, false otherwise.
+ * @param ps The {@link PreparedStatement} to be executed.
+ * @param rsh The handler that converts the results into an object.
+ * @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.
+ */
+ public QueryCallableStatement(final Connection conn, final boolean closeConn, final PreparedStatement ps,
+ final ResultSetHandler<T> rsh, final String sql, final Object... params) {
+ this.sql = sql;
+ this.params = params;
+ this.conn = conn;
+ this.closeConn = closeConn;
+ this.ps = ps;
+ this.rsh = rsh;
+ }
+
+ /**
+ * The actual call to {@code handle()} method.
+ *
+ * @return an array of update counts containing one element for each command in the batch.
+ * @throws SQLException if a database access error occurs.
+ * @see ResultSetHandler#handle(ResultSet)
+ */
+ @Override
+ public T call() throws SQLException {
+ ResultSet rs = null;
+ T ret = null;
+
+ try {
+ rs = wrap(ps.executeQuery());
+ ret = rsh.handle(rs);
+ } catch (final SQLException e) {
+ rethrow(e, sql, params);
+ } finally {
+ try {
+ close(rs);
+ } finally {
+ close(ps);
+ if (closeConn) {
+ close(conn);
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ }
+
+ /**
+ * Execute an SQL SELECT query with replacement parameters. The
+ * caller is responsible for closing the connection.
+ * @param <T> The type of object that the handler returns
+ * @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 A {@code Future} which returns the result of the query call.
+ * @throws SQLException if a database access error occurs
+ */
+ public <T> Future<T> query(final Connection conn, final String sql, final ResultSetHandler<T> rsh, final Object... params)
+ throws SQLException {
+ return executorService.submit(new Callable<T>() {
+
+ @Override
+ public T call() throws Exception {
+ return queryRunner.query(conn, sql, rsh, params);
+ }
+
+ });
+ }
+
+ /**
+ * 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 A {@code Future} which returns the result of the query call.
+ * @throws SQLException if a database access error occurs
+ */
+ public <T> Future<T> query(final Connection conn, final String sql, final ResultSetHandler<T> rsh) throws SQLException {
+ return executorService.submit(new Callable<T>() {
+
+ @Override
+ public T call() throws Exception {
+ return queryRunner.query(conn, sql, rsh);
+ }
+
+ });
+ }
+
+ /**
+ * 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 A {@code Future} which returns the result of the query call.
+ * @throws SQLException if a database access error occurs
+ */
+ public <T> Future<T> query(final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
+ return executorService.submit(new Callable<T>() {
+
+ @Override
+ public T call() throws Exception {
+ return queryRunner.query(sql, rsh, params);
+ }
+
+ });
+ }
+
+ /**
+ * 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 A {@code Future} which returns the result of the query call.
+ * @throws SQLException if a database access error occurs
+ */
+ public <T> Future<T> query(final String sql, final ResultSetHandler<T> rsh) throws SQLException {
+ return executorService.submit(new Callable<T>() {
+
+ @Override
+ public T call() throws Exception {
+ return queryRunner.query(sql, rsh);
+ }
+
+ });
+ }
+
+ /**
+ * @deprecated No longer used by this class. Will be removed in a future version.
+ * Class that encapsulates the continuation for update calls.
+ */
+ @Deprecated
+ protected class UpdateCallableStatement implements Callable<Integer> {
+ private final String sql;
+ private final Object[] params;
+ private final Connection conn;
+ private final boolean closeConn;
+ private final PreparedStatement ps;
+
+ /**
+ *
+ *
+ * @param conn The connection to use for the batch call.
+ * @param closeConn True if the connection should be closed, false otherwise.
+ * @param ps The {@link PreparedStatement} to be executed.
+ * @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.
+ */
+ public UpdateCallableStatement(final Connection conn, final boolean closeConn, final PreparedStatement ps, final String sql, final Object... params) {
+ this.sql = sql;
+ this.params = params;
+ this.conn = conn;
+ this.closeConn = closeConn;
+ this.ps = ps;
+ }
+
+ /**
+ * The actual call to {@code executeUpdate()} method.
+ *
+ * @return either (1) the row count for SQL Data Manipulation Language (DML) statements or
+ * (2) 0 for SQL statements that return nothing
+ * @throws SQLException if a database access error occurs.
+ * @see PreparedStatement#executeUpdate()
+ */
+ @Override
+ public Integer call() throws SQLException {
+ int rows = 0;
+
+ try {
+ rows = ps.executeUpdate();
+ } catch (final SQLException e) {
+ rethrow(e, sql, params);
+ } finally {
+ close(ps);
+ if (closeConn) {
+ close(conn);
+ }
+ }
+
+ return Integer.valueOf(rows);
+ }
+
+ }
+
+ /**
+ * 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 A {@code Future} which returns the number of rows updated.
+ * @throws SQLException if a database access error occurs
+ */
+ public Future<Integer> update(final Connection conn, final String sql) throws SQLException {
+ return executorService.submit(new Callable<Integer>() {
+
+ @Override
+ public Integer call() throws Exception {
+ return Integer.valueOf(queryRunner.update(conn, sql));
+ }
+
+ });
+ }
+
+ /**
+ * 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 A {@code Future} which returns the number of rows updated.
+ * @throws SQLException if a database access error occurs
+ */
+ public Future<Integer> update(final Connection conn, final String sql, final Object param) throws SQLException {
+ return executorService.submit(new Callable<Integer>() {
+
+ @Override
+ public Integer call() throws Exception {
+ return Integer.valueOf(queryRunner.update(conn, 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 A {@code Future} which returns the number of rows updated.
+ * @throws SQLException if a database access error occurs
+ */
+ public Future<Integer> update(final Connection conn, final String sql, final Object... params) throws SQLException {
+ return executorService.submit(new Callable<Integer>() {
+
+ @Override
+ public Integer call() throws Exception {
+ return Integer.valueOf(queryRunner.update(conn, 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 A {@code Future} which returns the number of rows updated.
+ */
+ public Future<Integer> update(final String sql) throws SQLException {
+ return executorService.submit(new Callable<Integer>() {
+
+ @Override
+ public Integer call() throws Exception {
+ return Integer.valueOf(queryRunner.update(sql));
+ }
+
+ });
+ }
+
+ /**
+ * 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 A {@code Future} which returns the number of rows updated.
+ */
+ public Future<Integer> update(final String sql, final Object param) throws SQLException {
+ return executorService.submit(new Callable<Integer>() {
+
+ @Override
+ public Integer call() throws Exception {
+ return Integer.valueOf(queryRunner.update(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 A {@code Future} which returns the number of rows updated.
+ */
+ public Future<Integer> update(final String sql, final Object... params) throws SQLException {
+ return executorService.submit(new Callable<Integer>() {
+
+ @Override
+ public Integer call() throws Exception {
+ return Integer.valueOf(queryRunner.update(sql, params));
+ }
+
+ });
+ }
+
+ /**
+ * Executes {@link QueryRunner#insert(String, ResultSetHandler)} asynchronously.
+ *
+ * @param <T> Return type expected
+ * @param sql SQL insert statement to execute
+ * @param rsh {@link ResultSetHandler} for handling the results
+ * @return {@link Future} that executes a query runner insert
+ * @see QueryRunner#insert(String, ResultSetHandler)
+ * @throws SQLException if a database access error occurs
+ * @since 1.6
+ */
+ public <T> Future<T> insert(final String sql, final ResultSetHandler<T> rsh) throws SQLException {
+ return executorService.submit(new Callable<T>() {
+
+ @Override
+ public T call() throws Exception {
+ return queryRunner.insert(sql, rsh);
+ }
+
+ });
+ }
+
+ /**
+ * Executes {@link QueryRunner#insert(String, ResultSetHandler, Object...)} asynchronously.
+ *
+ * @param <T> Return type expected
+ * @param sql SQL insert statement to execute
+ * @param rsh {@link ResultSetHandler} for handling the results
+ * @param params Parameter values for substitution in the SQL statement
+ * @return {@link Future} that executes a query runner insert
+ * @see QueryRunner#insert(String, ResultSetHandler, Object...)
+ * @throws SQLException if a database access error occurs
+ * @since 1.6
+ */
+ public <T> Future<T> insert(final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
+ return executorService.submit(new Callable<T>() {
+
+ @Override
+ public T call() throws Exception {
+ return queryRunner.insert(sql, rsh, params);
+ }
+ });
+ }
+
+ /**
+ * Executes {@link QueryRunner#insert(Connection, String, ResultSetHandler)} asynchronously.
+ *
+ * @param <T> Return type expected
+ * @param conn {@link Connection} to use to execute the SQL statement
+ * @param sql SQL insert statement to execute
+ * @param rsh {@link ResultSetHandler} for handling the results
+ * @return {@link Future} that executes a query runner insert
+ * @see QueryRunner#insert(Connection, String, ResultSetHandler)
+ * @throws SQLException if a database access error occurs
+ * @since 1.6
+ */
+ public <T> Future<T> insert(final Connection conn, final String sql, final ResultSetHandler<T> rsh) throws SQLException {
+ return executorService.submit(new Callable<T>() {
+
+ @Override
+ public T call() throws Exception {
+ return queryRunner.insert(conn, sql, rsh);
+ }
+ });
+ }
+
+ /**
+ * Executes {@link QueryRunner#insert(Connection, String, ResultSetHandler, Object...)} asynchronously.
+ *
+ * @param <T> Return type expected
+ * @param conn {@link Connection} to use to execute the SQL statement
+ * @param sql SQL insert statement to execute
+ * @param rsh {@link ResultSetHandler} for handling the results
+ * @param params Parameter values for substitution in the SQL statement
+ * @return {@link Future} that executes a query runner insert
+ * @see QueryRunner#insert(Connection, String, ResultSetHandler, Object...)
+ * @throws SQLException if a database access error occurs
+ * @since 1.6
+ */
+ public <T> Future<T> insert(final Connection conn, final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
+ return executorService.submit(new Callable<T>() {
+
+ @Override
+ public T call() throws Exception {
+ return queryRunner.insert(conn, sql, rsh, params);
+ }
+ });
+ }
+
+ /**
+ * {@link QueryRunner#insertBatch(String, ResultSetHandler, Object[][])} asynchronously.
+ *
+ * @param <T> Return type expected
+ * @param sql SQL insert statement to execute
+ * @param rsh {@link ResultSetHandler} for handling the results
+ * @param params An array of query replacement parameters. Each row in
+ * this array is one set of batch replacement values.
+ * @return {@link Future} that executes a query runner batch insert
+ * @see QueryRunner#insertBatch(String, ResultSetHandler, Object[][])
+ * @throws SQLException if a database access error occurs
+ * @since 1.6
+ */
+ public <T> Future<T> insertBatch(final String sql, final ResultSetHandler<T> rsh, final Object[][] params) throws SQLException {
+ return executorService.submit(new Callable<T>() {
+
+ @Override
+ public T call() throws Exception {
+ return queryRunner.insertBatch(sql, rsh, params);
+ }
+ });
+ }
+
+ /**
+ * {@link QueryRunner#insertBatch(Connection, String, ResultSetHandler, Object[][])} asynchronously.
+ *
+ * @param <T> Return type expected
+ * @param conn {@link Connection} to use to execute the SQL statement
+ * @param sql SQL insert statement to execute
+ * @param rsh {@link ResultSetHandler} for handling the results
+ * @param params An array of query replacement parameters. Each row in
+ * this array is one set of batch replacement values.
+ * @return {@link Future} that executes a query runner batch insert
+ * @see QueryRunner#insertBatch(Connection, String, ResultSetHandler, Object[][])
+ * @throws SQLException if a database access error occurs
+ * @since 1.6
+ */
+ public <T> Future<T> insertBatch(final Connection conn, final String sql, final ResultSetHandler<T> rsh, final Object[][] params) throws SQLException {
+ return executorService.submit(new Callable<T>() {
+
+ @Override
+ public T call() throws Exception {
+ return queryRunner.insertBatch(conn, sql, rsh, params);
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/org/apache/commons/dbutils/BasicRowProcessor.java b/src/main/java/org/apache/commons/dbutils/BasicRowProcessor.java
index fdfd0da..8af06c2 100644
--- a/src/main/java/org/apache/commons/dbutils/BasicRowProcessor.java
+++ b/src/main/java/org/apache/commons/dbutils/BasicRowProcessor.java
@@ -80,7 +80,7 @@ public class BasicRowProcessor implements RowProcessor {
* BasicRowProcessor constructor.
* @param convert The BeanProcessor to use when converting columns to
* bean properties.
- * @since DbUtils 1.1
+ * @since 1.1
*/
public BasicRowProcessor(final BeanProcessor convert) {
this.convert = convert;
diff --git a/src/main/java/org/apache/commons/dbutils/BeanProcessor.java b/src/main/java/org/apache/commons/dbutils/BeanProcessor.java
index 1542475..884c801 100644
--- a/src/main/java/org/apache/commons/dbutils/BeanProcessor.java
+++ b/src/main/java/org/apache/commons/dbutils/BeanProcessor.java
@@ -49,7 +49,7 @@ import java.util.ServiceLoader;
*
* @see BasicRowProcessor
*
- * @since DbUtils 1.1
+ * @since 1.1
*/
public class BeanProcessor {
diff --git a/src/main/java/org/apache/commons/dbutils/DbUtils.java b/src/main/java/org/apache/commons/dbutils/DbUtils.java
index fa290dd..d178db0 100644
--- a/src/main/java/org/apache/commons/dbutils/DbUtils.java
+++ b/src/main/java/org/apache/commons/dbutils/DbUtils.java
@@ -1,426 +1,426 @@
-/*
- * 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 static java.sql.DriverManager.registerDriver;
-
-import java.io.PrintWriter;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.sql.Connection;
-import java.sql.Driver;
-import java.sql.DriverPropertyInfo;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.SQLFeatureNotSupportedException;
-import java.sql.Statement;
-import java.util.logging.Logger;
-import java.util.Properties;
-
-/**
- * A collection of JDBC helper methods. This class is thread safe.
- */
-public final class DbUtils {
-
- /**
- * Default constructor.
- *
- * Utility classes should not have a public or default constructor,
- * but this one preserves retro-compatibility.
- *
- * @since 1.4
- */
- public DbUtils() {
- // do nothing
- }
-
- /**
- * Close a {@code Connection}, avoid closing if null.
- *
- * @param conn Connection to close.
- * @throws SQLException if a database access error occurs
- */
- public static void close(final Connection conn) throws SQLException {
- if (conn != null) {
- conn.close();
- }
- }
-
- /**
- * Close a {@code ResultSet}, avoid closing if null.
- *
- * @param rs ResultSet to close.
- * @throws SQLException if a database access error occurs
- */
- public static void close(final ResultSet rs) throws SQLException {
- if (rs != null) {
- rs.close();
- }
- }
-
- /**
- * Close a {@code Statement}, avoid closing if null.
- *
- * @param stmt Statement to close.
- * @throws SQLException if a database access error occurs
- */
- public static void close(final Statement stmt) throws SQLException {
- if (stmt != null) {
- stmt.close();
- }
- }
-
- /**
- * Close a {@code Connection}, avoid closing if null and hide
- * any SQLExceptions that occur.
- *
- * @param conn Connection to close.
- */
- public static void closeQuietly(final Connection conn) {
- try {
- close(conn);
- } catch (final SQLException e) { // NOPMD
- // quiet
- }
- }
-
- /**
- * Close a {@code Connection}, {@code Statement} and
- * {@code ResultSet}. Avoid closing if null and hide any
- * SQLExceptions that occur.
- *
- * @param conn Connection to close.
- * @param stmt Statement to close.
- * @param rs ResultSet to close.
- */
- public static void closeQuietly(final Connection conn, final Statement stmt,
- final ResultSet rs) {
-
- try {
- closeQuietly(rs);
- } finally {
- try {
- closeQuietly(stmt);
- } finally {
- closeQuietly(conn);
- }
- }
-
- }
-
- /**
- * Close a {@code ResultSet}, avoid closing if null and hide any
- * SQLExceptions that occur.
- *
- * @param rs ResultSet to close.
- */
- public static void closeQuietly(final ResultSet rs) {
- try {
- close(rs);
- } catch (final SQLException e) { // NOPMD
- // quiet
- }
- }
-
- /**
- * Close a {@code Statement}, avoid closing if null and hide
- * any SQLExceptions that occur.
- *
- * @param stmt Statement to close.
- */
- public static void closeQuietly(final Statement stmt) {
- try {
- close(stmt);
- } catch (final SQLException e) { // NOPMD
- // quiet
- }
- }
-
- /**
- * Commits a {@code Connection} then closes it, avoid closing if null.
- *
- * @param conn Connection to close.
- * @throws SQLException if a database access error occurs
- */
- public static void commitAndClose(final Connection conn) throws SQLException {
- if (conn != null) {
- try {
- conn.commit();
- } finally {
- conn.close();
- }
- }
- }
-
- /**
- * Commits a {@code Connection} then closes it, avoid closing if null
- * and hide any SQLExceptions that occur.
- *
- * @param conn Connection to close.
- */
- public static void commitAndCloseQuietly(final Connection conn) {
- try {
- commitAndClose(conn);
- } catch (final SQLException e) { // NOPMD
- // quiet
- }
- }
-
- /**
- * Loads and registers a database driver class.
- * If this succeeds, it returns true, else it returns false.
- *
- * @param driverClassName of driver to load
- * @return boolean {@code true} if the driver was found, otherwise {@code false}
- */
- public static boolean loadDriver(final String driverClassName) {
- return loadDriver(DbUtils.class.getClassLoader(), driverClassName);
- }
-
- /**
- * Loads and registers a database driver class.
- * If this succeeds, it returns true, else it returns false.
- *
- * @param classLoader the class loader used to load the driver class
- * @param driverClassName of driver to load
- * @return boolean {@code true} if the driver was found, otherwise {@code false}
- * @since 1.4
- */
- public static boolean loadDriver(final ClassLoader classLoader, final String driverClassName) {
- try {
- final Class<?> loadedClass = classLoader.loadClass(driverClassName);
-
- if (!Driver.class.isAssignableFrom(loadedClass)) {
- return false;
- }
-
- @SuppressWarnings("unchecked") // guarded by previous check
- final
- Class<Driver> driverClass = (Class<Driver>) loadedClass;
- final Constructor<Driver> driverConstructor = driverClass.getConstructor();
-
- // make Constructor accessible if it is private
- @SuppressWarnings("deprecation")
- // TODO This is deprecated in Java9 and canAccess() should be used. Adding suppression for building on
- // later JDKs without a warning.
- final boolean isConstructorAccessible = driverConstructor.isAccessible();
- if (!isConstructorAccessible) {
- driverConstructor.setAccessible(true);
- }
-
- try {
- final Driver driver = driverConstructor.newInstance();
- registerDriver(new DriverProxy(driver));
- } finally {
- driverConstructor.setAccessible(isConstructorAccessible);
- }
-
- return true;
- } catch (final Exception e) {
- return false;
- }
- }
-
- /**
- * Print the stack trace for a SQLException to STDERR.
- *
- * @param e SQLException to print stack trace of
- */
- public static void printStackTrace(final SQLException e) {
- printStackTrace(e, new PrintWriter(System.err));
- }
-
- /**
- * Print the stack trace for a SQLException to a
- * specified PrintWriter.
- *
- * @param e SQLException to print stack trace of
- * @param pw PrintWriter to print to
- */
- public static void printStackTrace(final SQLException e, final PrintWriter pw) {
-
- SQLException next = e;
- while (next != null) {
- next.printStackTrace(pw);
- next = next.getNextException();
- if (next != null) {
- pw.println("Next SQLException:");
- }
- }
- }
-
- /**
- * Print warnings on a Connection to STDERR.
- *
- * @param conn Connection to print warnings from
- */
- public static void printWarnings(final Connection conn) {
- printWarnings(conn, new PrintWriter(System.err));
- }
-
- /**
- * Print warnings on a Connection to a specified PrintWriter.
- *
- * @param conn Connection to print warnings from
- * @param pw PrintWriter to print to
- */
- public static void printWarnings(final Connection conn, final PrintWriter pw) {
- if (conn != null) {
- try {
- printStackTrace(conn.getWarnings(), pw);
- } catch (final SQLException e) {
- printStackTrace(e, pw);
- }
- }
- }
-
- /**
- * Rollback any changes made on the given connection.
- * @param conn Connection to rollback. A null value is legal.
- * @throws SQLException if a database access error occurs
- */
- public static void rollback(final Connection conn) throws SQLException {
- if (conn != null) {
- conn.rollback();
- }
- }
-
- /**
- * Performs a rollback on the {@code Connection} then closes it,
- * avoid closing if null.
- *
- * @param conn Connection to rollback. A null value is legal.
- * @throws SQLException if a database access error occurs
- * @since DbUtils 1.1
- */
- public static void rollbackAndClose(final Connection conn) throws SQLException {
- if (conn != null) {
- try {
- conn.rollback();
- } finally {
- conn.close();
- }
- }
- }
-
- /**
- * Performs a rollback on the {@code Connection} then closes it,
- * avoid closing if null and hide any SQLExceptions that occur.
- *
- * @param conn Connection to rollback. A null value is legal.
- * @since DbUtils 1.1
- */
- public static void rollbackAndCloseQuietly(final Connection conn) {
- try {
- rollbackAndClose(conn);
- } catch (final SQLException e) { // NOPMD
- // quiet
- }
- }
-
- /**
- * Simple {@link Driver} proxy class that proxies a JDBC Driver loaded dynamically.
- *
- * @since 1.6
- */
- static final class DriverProxy implements Driver {
-
- private boolean parentLoggerSupported = true;
-
- /**
- * The adapted JDBC Driver loaded dynamically.
- */
- private final Driver adapted;
-
- /**
- * Creates a new JDBC Driver that adapts a JDBC Driver loaded dynamically.
- *
- * @param adapted the adapted JDBC Driver loaded dynamically.
- */
- public DriverProxy(final Driver adapted) {
- this.adapted = adapted;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean acceptsURL(final String url) throws SQLException {
- return adapted.acceptsURL(url);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Connection connect(final String url, final Properties info) throws SQLException {
- return adapted.connect(url, info);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int getMajorVersion() {
- return adapted.getMajorVersion();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int getMinorVersion() {
- return adapted.getMinorVersion();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public DriverPropertyInfo[] getPropertyInfo(final String url, final Properties info) throws SQLException {
- return adapted.getPropertyInfo(url, info);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean jdbcCompliant() {
- return adapted.jdbcCompliant();
- }
-
- /**
- * Java 1.7 method.
- */
- @Override
- public Logger getParentLogger() throws SQLFeatureNotSupportedException {
- if (parentLoggerSupported) {
- try {
- final Method method = adapted.getClass().getMethod("getParentLogger");
- return (Logger)method.invoke(adapted);
- } catch (final NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
- parentLoggerSupported = false;
- throw new SQLFeatureNotSupportedException(e);
- }
- }
- throw new SQLFeatureNotSupportedException();
- }
-
- }
-
-}
+/*
+ * 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 static java.sql.DriverManager.registerDriver;
+
+import java.io.PrintWriter;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverPropertyInfo;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.sql.Statement;
+import java.util.logging.Logger;
+import java.util.Properties;
+
+/**
+ * A collection of JDBC helper methods. This class is thread safe.
+ */
+public final class DbUtils {
+
+ /**
+ * Default constructor.
+ *
+ * Utility classes should not have a public or default constructor,
+ * but this one preserves retro-compatibility.
+ *
+ * @since 1.4
+ */
+ public DbUtils() {
+ // do nothing
+ }
+
+ /**
+ * Close a {@code Connection}, avoid closing if null.
+ *
+ * @param conn Connection to close.
+ * @throws SQLException if a database access error occurs
+ */
+ public static void close(final Connection conn) throws SQLException {
+ if (conn != null) {
+ conn.close();
+ }
+ }
+
+ /**
+ * Close a {@code ResultSet}, avoid closing if null.
+ *
+ * @param rs ResultSet to close.
+ * @throws SQLException if a database access error occurs
+ */
+ public static void close(final ResultSet rs) throws SQLException {
+ if (rs != null) {
+ rs.close();
+ }
+ }
+
+ /**
+ * Close a {@code Statement}, avoid closing if null.
+ *
+ * @param stmt Statement to close.
+ * @throws SQLException if a database access error occurs
+ */
+ public static void close(final Statement stmt) throws SQLException {
+ if (stmt != null) {
+ stmt.close();
+ }
+ }
+
+ /**
+ * Close a {@code Connection}, avoid closing if null and hide
+ * any SQLExceptions that occur.
+ *
+ * @param conn Connection to close.
+ */
+ public static void closeQuietly(final Connection conn) {
+ try {
+ close(conn);
+ } catch (final SQLException e) { // NOPMD
+ // quiet
+ }
+ }
+
+ /**
+ * Close a {@code Connection}, {@code Statement} and
+ * {@code ResultSet}. Avoid closing if null and hide any
+ * SQLExceptions that occur.
+ *
+ * @param conn Connection to close.
+ * @param stmt Statement to close.
+ * @param rs ResultSet to close.
+ */
+ public static void closeQuietly(final Connection conn, final Statement stmt,
+ final ResultSet rs) {
+
+ try {
+ closeQuietly(rs);
+ } finally {
+ try {
+ closeQuietly(stmt);
+ } finally {
+ closeQuietly(conn);
+ }
+ }
+
+ }
+
+ /**
+ * Close a {@code ResultSet}, avoid closing if null and hide any
+ * SQLExceptions that occur.
+ *
+ * @param rs ResultSet to close.
+ */
+ public static void closeQuietly(final ResultSet rs) {
+ try {
+ close(rs);
+ } catch (final SQLException e) { // NOPMD
+ // quiet
+ }
+ }
+
+ /**
+ * Close a {@code Statement}, avoid closing if null and hide
+ * any SQLExceptions that occur.
+ *
+ * @param stmt Statement to close.
+ */
+ public static void closeQuietly(final Statement stmt) {
+ try {
+ close(stmt);
+ } catch (final SQLException e) { // NOPMD
+ // quiet
+ }
+ }
+
+ /**
+ * Commits a {@code Connection} then closes it, avoid closing if null.
+ *
+ * @param conn Connection to close.
+ * @throws SQLException if a database access error occurs
+ */
+ public static void commitAndClose(final Connection conn) throws SQLException {
+ if (conn != null) {
+ try {
+ conn.commit();
+ } finally {
+ conn.close();
+ }
+ }
+ }
+
+ /**
+ * Commits a {@code Connection} then closes it, avoid closing if null
+ * and hide any SQLExceptions that occur.
+ *
+ * @param conn Connection to close.
+ */
+ public static void commitAndCloseQuietly(final Connection conn) {
+ try {
+ commitAndClose(conn);
+ } catch (final SQLException e) { // NOPMD
+ // quiet
+ }
+ }
+
+ /**
+ * Loads and registers a database driver class.
+ * If this succeeds, it returns true, else it returns false.
+ *
+ * @param driverClassName of driver to load
+ * @return boolean {@code true} if the driver was found, otherwise {@code false}
+ */
+ public static boolean loadDriver(final String driverClassName) {
+ return loadDriver(DbUtils.class.getClassLoader(), driverClassName);
+ }
+
+ /**
+ * Loads and registers a database driver class.
+ * If this succeeds, it returns true, else it returns false.
+ *
+ * @param classLoader the class loader used to load the driver class
+ * @param driverClassName of driver to load
+ * @return boolean {@code true} if the driver was found, otherwise {@code false}
+ * @since 1.4
+ */
+ public static boolean loadDriver(final ClassLoader classLoader, final String driverClassName) {
+ try {
+ final Class<?> loadedClass = classLoader.loadClass(driverClassName);
+
+ if (!Driver.class.isAssignableFrom(loadedClass)) {
+ return false;
+ }
+
+ @SuppressWarnings("unchecked") // guarded by previous check
+ final
+ Class<Driver> driverClass = (Class<Driver>) loadedClass;
+ final Constructor<Driver> driverConstructor = driverClass.getConstructor();
+
+ // make Constructor accessible if it is private
+ @SuppressWarnings("deprecation")
+ // TODO This is deprecated in Java9 and canAccess() should be used. Adding suppression for building on
+ // later JDKs without a warning.
+ final boolean isConstructorAccessible = driverConstructor.isAccessible();
+ if (!isConstructorAccessible) {
+ driverConstructor.setAccessible(true);
+ }
+
+ try {
+ final Driver driver = driverConstructor.newInstance();
+ registerDriver(new DriverProxy(driver));
+ } finally {
+ driverConstructor.setAccessible(isConstructorAccessible);
+ }
+
+ return true;
+ } catch (final Exception e) {
+ return false;
+ }
+ }
+
+ /**
+ * Print the stack trace for a SQLException to STDERR.
+ *
+ * @param e SQLException to print stack trace of
+ */
+ public static void printStackTrace(final SQLException e) {
+ printStackTrace(e, new PrintWriter(System.err));
+ }
+
+ /**
+ * Print the stack trace for a SQLException to a
+ * specified PrintWriter.
+ *
+ * @param e SQLException to print stack trace of
+ * @param pw PrintWriter to print to
+ */
+ public static void printStackTrace(final SQLException e, final PrintWriter pw) {
+
+ SQLException next = e;
+ while (next != null) {
+ next.printStackTrace(pw);
+ next = next.getNextException();
+ if (next != null) {
+ pw.println("Next SQLException:");
+ }
+ }
+ }
+
+ /**
+ * Print warnings on a Connection to STDERR.
+ *
+ * @param conn Connection to print warnings from
+ */
+ public static void printWarnings(final Connection conn) {
+ printWarnings(conn, new PrintWriter(System.err));
+ }
+
+ /**
+ * Print warnings on a Connection to a specified PrintWriter.
+ *
+ * @param conn Connection to print warnings from
+ * @param pw PrintWriter to print to
+ */
+ public static void printWarnings(final Connection conn, final PrintWriter pw) {
+ if (conn != null) {
+ try {
+ printStackTrace(conn.getWarnings(), pw);
+ } catch (final SQLException e) {
+ printStackTrace(e, pw);
+ }
+ }
+ }
+
+ /**
+ * Rollback any changes made on the given connection.
+ * @param conn Connection to rollback. A null value is legal.
+ * @throws SQLException if a database access error occurs
+ */
+ public static void rollback(final Connection conn) throws SQLException {
+ if (conn != null) {
+ conn.rollback();
+ }
+ }
+
+ /**
+ * Performs a rollback on the {@code Connection} then closes it,
+ * avoid closing if null.
+ *
+ * @param conn Connection to rollback. A null value is legal.
+ * @throws SQLException if a database access error occurs
+ * @since 1.1
+ */
+ public static void rollbackAndClose(final Connection conn) throws SQLException {
+ if (conn != null) {
+ try {
+ conn.rollback();
+ } finally {
+ conn.close();
+ }
+ }
+ }
+
+ /**
+ * Performs a rollback on the {@code Connection} then closes it,
+ * avoid closing if null and hide any SQLExceptions that occur.
+ *
+ * @param conn Connection to rollback. A null value is legal.
+ * @since 1.1
+ */
+ public static void rollbackAndCloseQuietly(final Connection conn) {
+ try {
+ rollbackAndClose(conn);
+ } catch (final SQLException e) { // NOPMD
+ // quiet
+ }
+ }
+
+ /**
+ * Simple {@link Driver} proxy class that proxies a JDBC Driver loaded dynamically.
+ *
+ * @since 1.6
+ */
+ static final class DriverProxy implements Driver {
+
+ private boolean parentLoggerSupported = true;
+
+ /**
+ * The adapted JDBC Driver loaded dynamically.
+ */
+ private final Driver adapted;
+
+ /**
+ * Creates a new JDBC Driver that adapts a JDBC Driver loaded dynamically.
+ *
+ * @param adapted the adapted JDBC Driver loaded dynamically.
+ */
+ public DriverProxy(final Driver adapted) {
+ this.adapted = adapted;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean acceptsURL(final String url) throws SQLException {
+ return adapted.acceptsURL(url);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Connection connect(final String url, final Properties info) throws SQLException {
+ return adapted.connect(url, info);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getMajorVersion() {
+ return adapted.getMajorVersion();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getMinorVersion() {
+ return adapted.getMinorVersion();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public DriverPropertyInfo[] getPropertyInfo(final String url, final Properties info) throws SQLException {
+ return adapted.getPropertyInfo(url, info);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean jdbcCompliant() {
+ return adapted.jdbcCompliant();
+ }
+
+ /**
+ * Java 1.7 method.
+ */
+ @Override
+ public Logger getParentLogger() throws SQLFeatureNotSupportedException {
+ if (parentLoggerSupported) {
+ try {
+ final Method method = adapted.getClass().getMethod("getParentLogger");
+ return (Logger)method.invoke(adapted);
+ } catch (final NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+ parentLoggerSupported = false;
+ throw new SQLFeatureNotSupportedException(e);
+ }
+ }
+ throw new SQLFeatureNotSupportedException();
+ }
+
+ }
+
+}
diff --git a/src/main/java/org/apache/commons/dbutils/QueryLoader.java b/src/main/java/org/apache/commons/dbutils/QueryLoader.java
index efc2ef6..c670404 100644
--- a/src/main/java/org/apache/commons/dbutils/QueryLoader.java
+++ b/src/main/java/org/apache/commons/dbutils/QueryLoader.java
@@ -1,142 +1,142 @@
-/*
- * 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.io.IOException;
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-import java.util.regex.Pattern;
-
-/**
- * {@code QueryLoader} is a registry for sets of queries so
- * that multiple copies of the same queries aren't loaded into memory.
- * This implementation loads properties files filled with query name to
- * SQL mappings. This class is thread safe.
- */
-public class QueryLoader {
-
- /**
- * The Singleton instance of this class.
- */
- private static final QueryLoader instance = new QueryLoader();
-
- /**
- * Matches .xml file extensions.
- */
- private static final Pattern dotXml = Pattern.compile(".+\\.[xX][mM][lL]");
-
- /**
- * Return an instance of this class.
- * @return The Singleton instance.
- */
- public static QueryLoader instance() {
- return instance;
- }
-
- /**
- * Maps query set names to Maps of their queries.
- */
- private final Map<String, Map<String, String>> queries = new HashMap<>();
-
- /**
- * QueryLoader constructor.
- */
- protected QueryLoader() {
- }
-
- /**
- * Loads a Map of query names to SQL values. The Maps are cached so a
- * subsequent request to load queries from the same path will return
- * the cached Map. The properties file to load can be in either
- * line-oriented or XML format. XML formatted properties files must use a
- * {@code .xml} file extension.
- *
- * @param path The path that the ClassLoader will use to find the file.
- * This is <strong>not</strong> a file system path. If you had a jarred
- * Queries.properties file in the com.yourcorp.app.jdbc package you would
- * pass "/com/yourcorp/app/jdbc/Queries.properties" to this method.
- * @throws IOException if a file access error occurs
- * @throws IllegalArgumentException if the ClassLoader can't find a file at
- * the given path.
- * @throws java.util.InvalidPropertiesFormatException if the XML properties file is
- * invalid
- * @return Map of query names to SQL values
- * @see java.util.Properties
- */
- public synchronized Map<String, String> load(final String path) throws IOException {
-
- Map<String, String> queryMap = this.queries.get(path);
-
- if (queryMap == null) {
- queryMap = this.loadQueries(path);
- this.queries.put(path, queryMap);
- }
-
- return queryMap;
- }
-
- /**
- * Loads a set of named queries into a Map object. This implementation
- * reads a properties file at the given path. The properties file can be
- * in either line-oriented or XML format. XML formatted properties files
- * must use a {@code .xml} file extension.
-
- * @param path The path that the ClassLoader will use to find the file.
- * @throws IOException if a file access error occurs
- * @throws IllegalArgumentException if the ClassLoader can't find a file at
- * the given path.
- * @throws java.util.InvalidPropertiesFormatException if the XML properties file is
- * invalid
- * @since DbUtils 1.1
- * @return Map of query names to SQL values
- * @see java.util.Properties
- */
- protected Map<String, String> loadQueries(final String path) throws IOException {
- // Findbugs flags getClass().getResource as a bad practice; maybe we should change the API?
- final Properties props;
- try (InputStream in = getClass().getResourceAsStream(path)) {
-
- if (in == null) {
- throw new IllegalArgumentException(path + " not found.");
- }
- props = new Properties();
- if (dotXml.matcher(path).matches()) {
- props.loadFromXML(in);
- } else {
- props.load(in);
- }
- }
-
- // Copy to HashMap for better performance
-
- @SuppressWarnings({"rawtypes", "unchecked" }) // load() always creates <String,String> entries
- final
- HashMap<String, String> hashMap = new HashMap(props);
- return hashMap;
- }
-
- /**
- * Removes the queries for the given path from the cache.
- * @param path The path that the queries were loaded from.
- */
- public synchronized void unload(final String path) {
- this.queries.remove(path);
- }
-
-}
+/*
+ * 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.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.regex.Pattern;
+
+/**
+ * {@code QueryLoader} is a registry for sets of queries so
+ * that multiple copies of the same queries aren't loaded into memory.
+ * This implementation loads properties files filled with query name to
+ * SQL mappings. This class is thread safe.
+ */
+public class QueryLoader {
+
+ /**
+ * The Singleton instance of this class.
+ */
+ private static final QueryLoader instance = new QueryLoader();
+
+ /**
+ * Matches .xml file extensions.
+ */
+ private static final Pattern dotXml = Pattern.compile(".+\\.[xX][mM][lL]");
+
+ /**
+ * Return an instance of this class.
+ * @return The Singleton instance.
+ */
+ public static QueryLoader instance() {
+ return instance;
+ }
+
+ /**
+ * Maps query set names to Maps of their queries.
+ */
+ private final Map<String, Map<String, String>> queries = new HashMap<>();
+
+ /**
+ * QueryLoader constructor.
+ */
+ protected QueryLoader() {
+ }
+
+ /**
+ * Loads a Map of query names to SQL values. The Maps are cached so a
+ * subsequent request to load queries from the same path will return
+ * the cached Map. The properties file to load can be in either
+ * line-oriented or XML format. XML formatted properties files must use a
+ * {@code .xml} file extension.
+ *
+ * @param path The path that the ClassLoader will use to find the file.
+ * This is <strong>not</strong> a file system path. If you had a jarred
+ * Queries.properties file in the com.yourcorp.app.jdbc package you would
+ * pass "/com/yourcorp/app/jdbc/Queries.properties" to this method.
+ * @throws IOException if a file access error occurs
+ * @throws IllegalArgumentException if the ClassLoader can't find a file at
+ * the given path.
+ * @throws java.util.InvalidPropertiesFormatException if the XML properties file is
+ * invalid
+ * @return Map of query names to SQL values
+ * @see java.util.Properties
+ */
+ public synchronized Map<String, String> load(final String path) throws IOException {
+
+ Map<String, String> queryMap = this.queries.get(path);
+
+ if (queryMap == null) {
+ queryMap = this.loadQueries(path);
+ this.queries.put(path, queryMap);
+ }
+
+ return queryMap;
+ }
+
+ /**
+ * Loads a set of named queries into a Map object. This implementation
+ * reads a properties file at the given path. The properties file can be
+ * in either line-oriented or XML format. XML formatted properties files
+ * must use a {@code .xml} file extension.
+
+ * @param path The path that the ClassLoader will use to find the file.
+ * @throws IOException if a file access error occurs
+ * @throws IllegalArgumentException if the ClassLoader can't find a file at
+ * the given path.
+ * @throws java.util.InvalidPropertiesFormatException if the XML properties file is
+ * invalid
+ * @since 1.1
+ * @return Map of query names to SQL values
+ * @see java.util.Properties
+ */
+ protected Map<String, String> loadQueries(final String path) throws IOException {
+ // Findbugs flags getClass().getResource as a bad practice; maybe we should change the API?
+ final Properties props;
+ try (InputStream in = getClass().getResourceAsStream(path)) {
+
+ if (in == null) {
+ throw new IllegalArgumentException(path + " not found.");
+ }
+ props = new Properties();
+ if (dotXml.matcher(path).matches()) {
+ props.loadFromXML(in);
+ } else {
+ props.load(in);
+ }
+ }
+
+ // Copy to HashMap for better performance
+
+ @SuppressWarnings({"rawtypes", "unchecked" }) // load() always creates <String,String> entries
+ final
+ HashMap<String, String> hashMap = new HashMap(props);
+ return hashMap;
+ }
+
+ /**
+ * Removes the queries for the given path from the cache.
+ * @param path The path that the queries were loaded from.
+ */
+ public synchronized void unload(final String path) {
+ this.queries.remove(path);
+ }
+
+}
diff --git a/src/main/java/org/apache/commons/dbutils/QueryRunner.java b/src/main/java/org/apache/commons/dbutils/QueryRunner.java
index 6a1aee1..a55e7d0 100644
--- a/src/main/java/org/apache/commons/dbutils/QueryRunner.java
+++ b/src/main/java/org/apache/commons/dbutils/QueryRunner.java
@@ -125,7 +125,7 @@ public class QueryRunner extends AbstractQueryRunner {
* 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
+ * @since 1.1
*/
public int[] batch(final Connection conn, final String sql, final Object[][] params) throws SQLException {
return this.batch(conn, false, sql, params);
@@ -142,7 +142,7 @@ public class QueryRunner extends AbstractQueryRunner {
* 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
+ * @since 1.1
*/
public int[] batch(final String sql, final Object[][] params) throws SQLException {
final Connection conn = this.prepareConnection();
diff --git a/src/main/java/org/apache/commons/dbutils/ResultSetIterator.java b/src/main/java/org/apache/commons/dbutils/ResultSetIterator.java
index b96f39e..6f5a83c 100644
--- a/src/main/java/org/apache/commons/dbutils/ResultSetIterator.java
+++ b/src/main/java/org/apache/commons/dbutils/ResultSetIterator.java
@@ -1,141 +1,141 @@
-/*
- * 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.ResultSet;
-import java.sql.SQLException;
-import java.util.Iterator;
-
-/**
- * <p>
- * Wraps a {@code ResultSet} in an {@code Iterator<Object[]>}. This is useful
- * when you want to present a non-database application layer with domain
- * neutral data.
- * </p>
- *
- * <p>
- * This implementation requires the {@code ResultSet.isLast()} method
- * to be implemented.
- * </p>
- */
-public class ResultSetIterator implements Iterator<Object[]> {
-
- /**
- * The wrapped {@code ResultSet}.
- */
- private final ResultSet rs;
-
- /**
- * The processor to use when converting a row into an Object[].
- */
- private final RowProcessor convert;
-
- /**
- * Constructor for ResultSetIterator.
- * @param rs Wrap this {@code ResultSet} in an {@code Iterator}.
- */
- public ResultSetIterator(final ResultSet rs) {
- this(rs, new BasicRowProcessor());
- }
-
- /**
- * Constructor for ResultSetIterator.
- * @param rs Wrap this {@code ResultSet} in an {@code Iterator}.
- * @param convert The processor to use when converting a row into an
- * {@code Object[]}. Defaults to a
- * {@code BasicRowProcessor}.
- */
- public ResultSetIterator(final ResultSet rs, final RowProcessor convert) {
- this.rs = rs;
- this.convert = convert;
- }
-
- /**
- * Returns true if there are more rows in the ResultSet.
- * @return boolean {@code true} if there are more rows
- * @throws RuntimeException if an SQLException occurs.
- */
- @Override
- public boolean hasNext() {
- try {
- return !rs.isLast();
- } catch (final SQLException e) {
- rethrow(e);
- return false;
- }
- }
-
- /**
- * Returns the next row as an {@code Object[]}.
- * @return An {@code Object[]} with the same number of elements as
- * columns in the {@code ResultSet}.
- * @see java.util.Iterator#next()
- * @throws RuntimeException if an SQLException occurs.
- */
- @Override
- public Object[] next() {
- try {
- rs.next();
- return this.convert.toArray(rs);
- } catch (final SQLException e) {
- rethrow(e);
- return null;
- }
- }
-
- /**
- * Deletes the current row from the {@code ResultSet}.
- * @see java.util.Iterator#remove()
- * @throws RuntimeException if an SQLException occurs.
- */
- @Override
- public void remove() {
- try {
- this.rs.deleteRow();
- } catch (final SQLException e) {
- rethrow(e);
- }
- }
-
- /**
- * Rethrow the SQLException as a RuntimeException. This implementation
- * creates a new RuntimeException with the SQLException's error message.
- * @param e SQLException to rethrow
- * @since DbUtils 1.1
- */
- protected void rethrow(final SQLException e) {
- throw new RuntimeException(e.getMessage());
- }
-
- /**
- * Generates an {@code Iterable}, suitable for use in for-each loops.
- *
- * @param rs Wrap this {@code ResultSet} in an {@code Iterator}.
- * @return an {@code Iterable}, suitable for use in for-each loops.
- */
- public static Iterable<Object[]> iterable(final ResultSet rs) {
- return new Iterable<Object[]>() {
-
- @Override
- public Iterator<Object[]> iterator() {
- return new ResultSetIterator(rs);
- }
-
- };
- }
-
-}
+/*
+ * 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.ResultSet;
+import java.sql.SQLException;
+import java.util.Iterator;
+
+/**
+ * <p>
+ * Wraps a {@code ResultSet} in an {@code Iterator<Object[]>}. This is useful
+ * when you want to present a non-database application layer with domain
+ * neutral data.
+ * </p>
+ *
+ * <p>
+ * This implementation requires the {@code ResultSet.isLast()} method
+ * to be implemented.
+ * </p>
+ */
+public class ResultSetIterator implements Iterator<Object[]> {
+
+ /**
+ * The wrapped {@code ResultSet}.
+ */
+ private final ResultSet rs;
+
+ /**
+ * The processor to use when converting a row into an Object[].
+ */
+ private final RowProcessor convert;
+
+ /**
+ * Constructor for ResultSetIterator.
+ * @param rs Wrap this {@code ResultSet} in an {@code Iterator}.
+ */
+ public ResultSetIterator(final ResultSet rs) {
+ this(rs, new BasicRowProcessor());
+ }
+
+ /**
+ * Constructor for ResultSetIterator.
+ * @param rs Wrap this {@code ResultSet} in an {@code Iterator}.
+ * @param convert The processor to use when converting a row into an
+ * {@code Object[]}. Defaults to a
+ * {@code BasicRowProcessor}.
+ */
+ public ResultSetIterator(final ResultSet rs, final RowProcessor convert) {
+ this.rs = rs;
+ this.convert = convert;
+ }
+
+ /**
+ * Returns true if there are more rows in the ResultSet.
+ * @return boolean {@code true} if there are more rows
+ * @throws RuntimeException if an SQLException occurs.
+ */
+ @Override
+ public boolean hasNext() {
+ try {
+ return !rs.isLast();
+ } catch (final SQLException e) {
+ rethrow(e);
+ return false;
+ }
+ }
+
+ /**
+ * Returns the next row as an {@code Object[]}.
+ * @return An {@code Object[]} with the same number of elements as
+ * columns in the {@code ResultSet}.
+ * @see java.util.Iterator#next()
+ * @throws RuntimeException if an SQLException occurs.
+ */
+ @Override
+ public Object[] next() {
+ try {
+ rs.next();
+ return this.convert.toArray(rs);
+ } catch (final SQLException e) {
+ rethrow(e);
+ return null;
+ }
+ }
+
+ /**
+ * Deletes the current row from the {@code ResultSet}.
+ * @see java.util.Iterator#remove()
+ * @throws RuntimeException if an SQLException occurs.
+ */
+ @Override
+ public void remove() {
+ try {
+ this.rs.deleteRow();
+ } catch (final SQLException e) {
+ rethrow(e);
+ }
+ }
+
+ /**
+ * Rethrow the SQLException as a RuntimeException. This implementation
+ * creates a new RuntimeException with the SQLException's error message.
+ * @param e SQLException to rethrow
+ * @since 1.1
+ */
+ protected void rethrow(final SQLException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+
+ /**
+ * Generates an {@code Iterable}, suitable for use in for-each loops.
+ *
+ * @param rs Wrap this {@code ResultSet} in an {@code Iterator}.
+ * @return an {@code Iterable}, suitable for use in for-each loops.
+ */
+ public static Iterable<Object[]> iterable(final ResultSet rs) {
+ return new Iterable<Object[]>() {
+
+ @Override
+ public Iterator<Object[]> iterator() {
+ return new ResultSetIterator(rs);
+ }
+
+ };
+ }
+
+}
diff --git a/src/main/java/org/apache/commons/dbutils/handlers/AbstractKeyedHandler.java b/src/main/java/org/apache/commons/dbutils/handlers/AbstractKeyedHandler.java
index 0432bb1..e2a692d 100644
--- a/src/main/java/org/apache/commons/dbutils/handlers/AbstractKeyedHandler.java
+++ b/src/main/java/org/apache/commons/dbutils/handlers/AbstractKeyedHandler.java
@@ -1,87 +1,87 @@
-/*
- * 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.handlers;
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.commons.dbutils.ResultSetHandler;
-
-/**
- * <p>
- * {@code ResultSetHandler} implementation that returns a Map.
- * {@code ResultSet} rows are converted into objects (Vs) which are then stored
- * in a Map under the given keys (Ks).
- * </p>
- *
- * @param <K> the type of keys maintained by the returned map
- * @param <V> the type of mapped values
- * @see org.apache.commons.dbutils.ResultSetHandler
- * @since DbUtils 1.3
- */
-public abstract class AbstractKeyedHandler<K, V> implements ResultSetHandler<Map<K, V>> {
-
-
- /**
- * Convert each row's columns into a Map and store then
- * in a {@code Map} under {@code ResultSet.getObject(key)} key.
- * @param rs {@code ResultSet} to process.
- * @return A {@code Map}, never {@code null}.
- * @throws SQLException if a database access error occurs
- * @see org.apache.commons.dbutils.ResultSetHandler#handle(java.sql.ResultSet)
- */
- @Override
- public Map<K, V> handle(final ResultSet rs) throws SQLException {
- final Map<K, V> result = createMap();
- while (rs.next()) {
- result.put(createKey(rs), createRow(rs));
- }
- return result;
- }
-
- /**
- * This factory method is called by {@code handle()} to create the Map
- * to store records in. This implementation returns a {@code HashMap}
- * instance.
- *
- * @return Map to store records in
- */
- protected Map<K, V> createMap() {
- return new HashMap<>();
- }
-
- /**
- * This factory method is called by {@code handle()} to retrieve the
- * key value from the current {@code ResultSet} row.
- * @param rs ResultSet to create a key from
- * @return K from the configured key column name/index
- * @throws SQLException if a database access error occurs
- */
- protected abstract K createKey(ResultSet rs) throws SQLException;
-
- /**
- * This factory method is called by {@code handle()} to store the
- * current {@code ResultSet} row in some object.
- * @param rs ResultSet to create a row from
- * @return V object created from the current row
- * @throws SQLException if a database access error occurs
- */
- protected abstract V createRow(ResultSet rs) throws SQLException;
-
-}
+/*
+ * 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.handlers;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.dbutils.ResultSetHandler;
+
+/**
+ * <p>
+ * {@code ResultSetHandler} implementation that returns a Map.
+ * {@code ResultSet} rows are converted into objects (Vs) which are then stored
+ * in a Map under the given keys (Ks).
+ * </p>
+ *
+ * @param <K> the type of keys maintained by the returned map
+ * @param <V> the type of mapped values
+ * @see org.apache.commons.dbutils.ResultSetHandler
+ * @since 1.3
+ */
+public abstract class AbstractKeyedHandler<K, V> implements ResultSetHandler<Map<K, V>> {
+
+
+ /**
+ * Convert each row's columns into a Map and store then
+ * in a {@code Map} under {@code ResultSet.getObject(key)} key.
+ * @param rs {@code ResultSet} to process.
+ * @return A {@code Map}, never {@code null}.
+ * @throws SQLException if a database access error occurs
+ * @see org.apache.commons.dbutils.ResultSetHandler#handle(java.sql.ResultSet)
+ */
+ @Override
+ public Map<K, V> handle(final ResultSet rs) throws SQLException {
+ final Map<K, V> result = createMap();
+ while (rs.next()) {
+ result.put(createKey(rs), createRow(rs));
+ }
+ return result;
+ }
+
+ /**
+ * This factory method is called by {@code handle()} to create the Map
+ * to store records in. This implementation returns a {@code HashMap}
+ * instance.
+ *
+ * @return Map to store records in
+ */
+ protected Map<K, V> createMap() {
+ return new HashMap<>();
+ }
+
+ /**
+ * This factory method is called by {@code handle()} to retrieve the
+ * key value from the current {@code ResultSet} row.
+ * @param rs ResultSet to create a key from
+ * @return K from the configured key column name/index
+ * @throws SQLException if a database access error occurs
+ */
+ protected abstract K createKey(ResultSet rs) throws SQLException;
+
+ /**
+ * This factory method is called by {@code handle()} to store the
+ * current {@code ResultSet} row in some object.
+ * @param rs ResultSet to create a row from
+ * @return V object created from the current row
+ * @throws SQLException if a database access error occurs
+ */
+ protected abstract V createRow(ResultSet rs) throws SQLException;
+
+}
diff --git a/src/main/java/org/apache/commons/dbutils/handlers/BeanMapHandler.java b/src/main/java/org/apache/commons/dbutils/handlers/BeanMapHandler.java
index e50d239..420300e 100644
--- a/src/main/java/org/apache/commons/dbutils/handlers/BeanMapHandler.java
+++ b/src/main/java/org/apache/commons/dbutils/handlers/BeanMapHandler.java
@@ -1,184 +1,184 @@
-/*
- * 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.handlers;
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-import org.apache.commons.dbutils.RowProcessor;
-
-/**
- * <p>
- * {@code ResultSetHandler} implementation that returns a Map of Beans.
- * {@code ResultSet} rows are converted into Beans which are then stored in
- * a Map under the given key.
- * </p>
- * <p>
- * If you had a Person table with a primary key column called ID, you could
- * retrieve rows from the table like this:
- *
- * <pre>
- * ResultSetHandler<Map<Long, Person>> h = new BeanMapHandler<Long, Person>(Person.class, "id");
- * Map<Long, Person> found = queryRunner.query("select id, name, age from person", h);
- * Person jane = found.get(1L); // jane's id is 1
- * String janesName = jane.getName();
- * Integer janesAge = jane.getAge();
- * </pre>
- *
- * Note that the "id" passed to BeanMapHandler can be in any case. The data type
- * returned for id is dependent upon how your JDBC driver converts SQL column
- * types from the Person table into Java types. The "name" and "age" columns are
- * converted according to their property descriptors by DbUtils.
- * </p>
- * <p>
- * This class is thread safe.
- * </p>
- *
- * @param <K>
- * the type of keys maintained by the returned map
- * @param <V>
- * the type of the bean
- * @see org.apache.commons.dbutils.ResultSetHandler
- * @since DbUtils 1.5
- */
-public class BeanMapHandler<K, V> extends AbstractKeyedHandler<K, V> {
-
- /**
- * The Class of beans produced by this handler.
- */
- private final Class<V> type;
-
- /**
- * The RowProcessor implementation to use when converting rows into Objects.
- */
- private final RowProcessor convert;
-
- /**
- * The column index to retrieve key values from. Defaults to 1.
- */
- private final int columnIndex;
-
- /**
- * The column name to retrieve key values from. Either columnName or
- * columnIndex will be used but never both.
- */
- private final String columnName;
-
- /**
- * Creates a new instance of BeanMapHandler. The value of the first column
- * of each row will be a key in the Map.
- *
- * @param type
- * The Class that objects returned from {@code createRow()}
- * are created from.
- */
- public BeanMapHandler(final Class<V> type) {
- this(type, ArrayHandler.ROW_PROCESSOR, 1, null);
- }
-
- /**
- * Creates a new instance of BeanMapHandler. The value of the first column
- * of each row will be a key in the Map.
- *
- * @param type
- * The Class that objects returned from {@code createRow()}
- * are created from.
- * @param convert
- * The {@code RowProcessor} implementation to use when
- * converting rows into Beans
- */
- public BeanMapHandler(final Class<V> type, final RowProcessor convert) {
- this(type, convert, 1, null);
- }
-
- /**
- * Creates a new instance of BeanMapHandler.
- *
- * @param type
- * The Class that objects returned from {@code createRow()}
- * are created from.
- * @param columnIndex
- * The values to use as keys in the Map are retrieved from the
- * column at this index.
- */
- public BeanMapHandler(final Class<V> type, final int columnIndex) {
- this(type, ArrayHandler.ROW_PROCESSOR, columnIndex, null);
- }
-
- /**
- * Creates a new instance of BeanMapHandler.
- *
- * @param type
- * The Class that objects returned from {@code createRow()}
- * are created from.
- * @param columnName
- * The values to use as keys in the Map are retrieved from the
- * column with this name.
- */
- public BeanMapHandler(final Class<V> type, final String columnName) {
- this(type, ArrayHandler.ROW_PROCESSOR, 1, columnName);
- }
-
- /**
- * Private Helper
- *
- * @param convert
- * The {@code RowProcessor} implementation to use when
- * converting rows into Beans
- * @param columnIndex
- * The values to use as keys in the Map are retrieved from the
- * column at this index.
- * @param columnName
- * The values to use as keys in the Map are retrieved from the
- * column with this name.
- */
- private BeanMapHandler(final Class<V> type, final RowProcessor convert,
- final int columnIndex, final String columnName) {
- this.type = type;
- this.convert = convert;
- this.columnIndex = columnIndex;
- this.columnName = columnName;
- }
-
- /**
- * This factory method is called by {@code handle()} to retrieve the
- * key value from the current {@code ResultSet} row.
- * @param rs ResultSet to create a key from
- *
- * @return K from the configured key column name/index
- *
- * @throws SQLException if a database access error occurs
- * @throws ClassCastException if the class datatype does not match the column type
- *
- * @see org.apache.commons.dbutils.handlers.AbstractKeyedHandler#createKey(ResultSet)
- */
- // We assume that the user has picked the correct type to match the column
- // so getObject will return the appropriate type and the cast will succeed.
- @SuppressWarnings("unchecked")
- @Override
- protected K createKey(final ResultSet rs) throws SQLException {
- return (columnName == null) ?
- (K) rs.getObject(columnIndex) :
- (K) rs.getObject(columnName);
- }
-
- @Override
- protected V createRow(final ResultSet rs) throws SQLException {
- return this.convert.toBean(rs, type);
- }
-
-}
+/*
+ * 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.handlers;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.apache.commons.dbutils.RowProcessor;
+
+/**
+ * <p>
+ * {@code ResultSetHandler} implementation that returns a Map of Beans.
+ * {@code ResultSet} rows are converted into Beans which are then stored in
+ * a Map under the given key.
+ * </p>
+ * <p>
+ * If you had a Person table with a primary key column called ID, you could
+ * retrieve rows from the table like this:
+ *
+ * <pre>
+ * ResultSetHandler<Map<Long, Person>> h = new BeanMapHandler<Long, Person>(Person.class, "id");
+ * Map<Long, Person> found = queryRunner.query("select id, name, age from person", h);
+ * Person jane = found.get(1L); // jane's id is 1
+ * String janesName = jane.getName();
+ * Integer janesAge = jane.getAge();
+ * </pre>
+ *
+ * Note that the "id" passed to BeanMapHandler can be in any case. The data type
+ * returned for id is dependent upon how your JDBC driver converts SQL column
+ * types from the Person table into Java types. The "name" and "age" columns are
+ * converted according to their property descriptors by DbUtils.
+ * </p>
+ * <p>
+ * This class is thread safe.
+ * </p>
+ *
+ * @param <K>
+ * the type of keys maintained by the returned map
+ * @param <V>
+ * the type of the bean
+ * @see org.apache.commons.dbutils.ResultSetHandler
+ * @since 1.5
+ */
+public class BeanMapHandler<K, V> extends AbstractKeyedHandler<K, V> {
+
+ /**
+ * The Class of beans produced by this handler.
+ */
+ private final Class<V> type;
+
+ /**
+ * The RowProcessor implementation to use when converting rows into Objects.
+ */
+ private final RowProcessor convert;
+
+ /**
+ * The column index to retrieve key values from. Defaults to 1.
+ */
+ private final int columnIndex;
+
+ /**
+ * The column name to retrieve key values from. Either columnName or
+ * columnIndex will be used but never both.
+ */
+ private final String columnName;
+
+ /**
+ * Creates a new instance of BeanMapHandler. The value of the first column
+ * of each row will be a key in the Map.
+ *
+ * @param type
+ * The Class that objects returned from {@code createRow()}
+ * are created from.
+ */
+ public BeanMapHandler(final Class<V> type) {
+ this(type, ArrayHandler.ROW_PROCESSOR, 1, null);
+ }
+
+ /**
+ * Creates a new instance of BeanMapHandler. The value of the first column
+ * of each row will be a key in the Map.
+ *
+ * @param type
+ * The Class that objects returned from {@code createRow()}
+ * are created from.
+ * @param convert
+ * The {@code RowProcessor} implementation to use when
+ * converting rows into Beans
+ */
+ public BeanMapHandler(final Class<V> type, final RowProcessor convert) {
+ this(type, convert, 1, null);
+ }
+
+ /**
+ * Creates a new instance of BeanMapHandler.
+ *
+ * @param type
+ * The Class that objects returned from {@code createRow()}
+ * are created from.
+ * @param columnIndex
+ * The values to use as keys in the Map are retrieved from the
+ * column at this index.
+ */
+ public BeanMapHandler(final Class<V> type, final int columnIndex) {
+ this(type, ArrayHandler.ROW_PROCESSOR, columnIndex, null);
+ }
+
+ /**
+ * Creates a new instance of BeanMapHandler.
+ *
+ * @param type
+ * The Class that objects returned from {@code createRow()}
+ * are created from.
+ * @param columnName
+ * The values to use as keys in the Map are retrieved from the
+ * column with this name.
+ */
+ public BeanMapHandler(final Class<V> type, final String columnName) {
+ this(type, ArrayHandler.ROW_PROCESSOR, 1, columnName);
+ }
+
+ /**
+ * Private Helper
+ *
+ * @param convert
+ * The {@code RowProcessor} implementation to use when
+ * converting rows into Beans
+ * @param columnIndex
+ * The values to use as keys in the Map are retrieved from the
+ * column at this index.
+ * @param columnName
+ * The values to use as keys in the Map are retrieved from the
+ * column with this name.
+ */
+ private BeanMapHandler(final Class<V> type, final RowProcessor convert,
+ final int columnIndex, final String columnName) {
+ this.type = type;
+ this.convert = convert;
+ this.columnIndex = columnIndex;
+ this.columnName = columnName;
+ }
+
+ /**
+ * This factory method is called by {@code handle()} to retrieve the
+ * key value from the current {@code ResultSet} row.
+ * @param rs ResultSet to create a key from
+ *
+ * @return K from the configured key column name/index
+ *
+ * @throws SQLException if a database access error occurs
+ * @throws ClassCastException if the class datatype does not match the column type
+ *
+ * @see org.apache.commons.dbutils.handlers.AbstractKeyedHandler#createKey(ResultSet)
+ */
+ // We assume that the user has picked the correct type to match the column
+ // so getObject will return the appropriate type and the cast will succeed.
+ @SuppressWarnings("unchecked")
+ @Override
+ protected K createKey(final ResultSet rs) throws SQLException {
+ return (columnName == null) ?
+ (K) rs.getObject(columnIndex) :
+ (K) rs.getObject(columnName);
+ }
+
+ @Override
+ protected V createRow(final ResultSet rs) throws SQLException {
+ return this.convert.toBean(rs, type);
+ }
+
+}
diff --git a/src/main/java/org/apache/commons/dbutils/handlers/ColumnListHandler.java b/src/main/java/org/apache/commons/dbutils/handlers/ColumnListHandler.java
index 0b3ba52..00b025e 100644
--- a/src/main/java/org/apache/commons/dbutils/handlers/ColumnListHandler.java
+++ b/src/main/java/org/apache/commons/dbutils/handlers/ColumnListHandler.java
@@ -1,104 +1,104 @@
-/*
- * 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.handlers;
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-/**
- * {@code ResultSetHandler} implementation that converts one
- * {@code ResultSet} column into a {@code List} of
- * {@code Object}s. This class is thread safe.
- *
- * @param <T> The type of the column.
- * @see org.apache.commons.dbutils.ResultSetHandler
- * @since DbUtils 1.1
- */
-public class ColumnListHandler<T> extends AbstractListHandler<T> {
-
- /**
- * The column number to retrieve.
- */
- private final int columnIndex;
-
- /**
- * The column name to retrieve. Either columnName or columnIndex
- * will be used but never both.
- */
- private final String columnName;
-
- /**
- * Creates a new instance of ColumnListHandler. The first column of each
- * row will be returned from {@code handle()}.
- */
- public ColumnListHandler() {
- this(1, null);
- }
-
- /**
- * Creates a new instance of ColumnListHandler.
- *
- * @param columnIndex The index of the column to retrieve from the
- * {@code ResultSet}.
- */
- public ColumnListHandler(final int columnIndex) {
- this(columnIndex, null);
- }
-
- /**
- * Creates a new instance of ColumnListHandler.
- *
- * @param columnName The name of the column to retrieve from the
- * {@code ResultSet}.
- */
- public ColumnListHandler(final String columnName) {
- this(1, columnName);
- }
-
- /** Private Helper
- * @param columnIndex The index of the column to retrieve from the
- * {@code ResultSet}.
- * @param columnName The name of the column to retrieve from the
- * {@code ResultSet}.
- */
- private ColumnListHandler(final int columnIndex, final String columnName) {
- this.columnIndex = columnIndex;
- this.columnName = columnName;
- }
-
- /**
- * Returns one {@code ResultSet} column value as {@code Object}.
- * @param rs {@code ResultSet} to process.
- * @return {@code Object}, never {@code null}.
- *
- * @throws SQLException if a database access error occurs
- * @throws ClassCastException if the class datatype does not match the column type
- *
- * @see org.apache.commons.dbutils.handlers.AbstractListHandler#handle(ResultSet)
- */
- // We assume that the user has picked the correct type to match the column
- // so getObject will return the appropriate type and the cast will succeed.
- @SuppressWarnings("unchecked")
- @Override
- protected T handleRow(final ResultSet rs) throws SQLException {
- if (this.columnName == null) {
- return (T) rs.getObject(this.columnIndex);
- }
- return (T) rs.getObject(this.columnName);
- }
-
-}
+/*
+ * 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.handlers;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * {@code ResultSetHandler} implementation that converts one
+ * {@code ResultSet} column into a {@code List} of
+ * {@code Object}s. This class is thread safe.
+ *
+ * @param <T> The type of the column.
+ * @see org.apache.commons.dbutils.ResultSetHandler
+ * @since 1.1
+ */
+public class ColumnListHandler<T> extends AbstractListHandler<T> {
+
+ /**
+ * The column number to retrieve.
+ */
+ private final int columnIndex;
+
+ /**
+ * The column name to retrieve. Either columnName or columnIndex
+ * will be used but never both.
+ */
+ private final String columnName;
+
+ /**
+ * Creates a new instance of ColumnListHandler. The first column of each
+ * row will be returned from {@code handle()}.
+ */
+ public ColumnListHandler() {
+ this(1, null);
+ }
+
+ /**
+ * Creates a new instance of ColumnListHandler.
+ *
+ * @param columnIndex The index of the column to retrieve from the
+ * {@code ResultSet}.
+ */
+ public ColumnListHandler(final int columnIndex) {
+ this(columnIndex, null);
+ }
+
+ /**
+ * Creates a new instance of ColumnListHandler.
+ *
+ * @param columnName The name of the column to retrieve from the
+ * {@code ResultSet}.
+ */
+ public ColumnListHandler(final String columnName) {
+ this(1, columnName);
+ }
+
+ /** Private Helper
+ * @param columnIndex The index of the column to retrieve from the
+ * {@code ResultSet}.
+ * @param columnName The name of the column to retrieve from the
+ * {@code ResultSet}.
+ */
+ private ColumnListHandler(final int columnIndex, final String columnName) {
+ this.columnIndex = columnIndex;
+ this.columnName = columnName;
+ }
+
+ /**
+ * Returns one {@code ResultSet} column value as {@code Object}.
+ * @param rs {@code ResultSet} to process.
+ * @return {@code Object}, never {@code null}.
+ *
+ * @throws SQLException if a database access error occurs
+ * @throws ClassCastException if the class datatype does not match the column type
+ *
+ * @see org.apache.commons.dbutils.handlers.AbstractListHandler#handle(ResultSet)
+ */
+ // We assume that the user has picked the correct type to match the column
+ // so getObject will return the appropriate type and the cast will succeed.
+ @SuppressWarnings("unchecked")
+ @Override
+ protected T handleRow(final ResultSet rs) throws SQLException {
+ if (this.columnName == null) {
+ return (T) rs.getObject(this.columnIndex);
+ }
+ return (T) rs.getObject(this.columnName);
+ }
+
+}
diff --git a/src/main/java/org/apache/commons/dbutils/handlers/KeyedHandler.java b/src/main/java/org/apache/commons/dbutils/handlers/KeyedHandler.java
index a2baa05..829f053 100644
--- a/src/main/java/org/apache/commons/dbutils/handlers/KeyedHandler.java
+++ b/src/main/java/org/apache/commons/dbutils/handlers/KeyedHandler.java
@@ -1,160 +1,160 @@
-/*
- * 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.handlers;
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Map;
-
-import org.apache.commons.dbutils.RowProcessor;
-
-/**
- * <p>
- * {@code ResultSetHandler} implementation that returns a Map of Maps.
- * {@code ResultSet} rows are converted into Maps which are then stored
- * in a Map under the given key.
- * </p>
- * <p>
- * If you had a Person table with a primary key column called ID, you could
- * retrieve rows from the table like this:
- * <pre>
- * ResultSetHandler h = new KeyedHandler("id");
- * Map found = (Map) queryRunner.query("select id, name, age from person", h);
- * Map jane = (Map) found.get(new Long(1)); // jane's id is 1
- * String janesName = (String) jane.get("name");
- * Integer janesAge = (Integer) jane.get("age");
- * </pre>
- * Note that the "id" passed to KeyedHandler and "name" and "age" passed to the
- * returned Map's get() method can be in any case. The data types returned for
- * name and age are dependent upon how your JDBC driver converts SQL column
- * types from the Person table into Java types.
- * </p>
- * <p>This class is thread safe.</p>
- *
- * @param <K> The type of the key
- * @see org.apache.commons.dbutils.ResultSetHandler
- * @since DbUtils 1.1
- */
-public class KeyedHandler<K> extends AbstractKeyedHandler<K, Map<String, Object>> {
-
- /**
- * The RowProcessor implementation to use when converting rows
- * into Objects.
- */
- protected final RowProcessor convert;
-
- /**
- * The column index to retrieve key values from. Defaults to 1.
- */
- protected final int columnIndex;
-
- /**
- * The column name to retrieve key values from. Either columnName or
- * columnIndex will be used but never both.
- */
- protected final String columnName;
-
- /**
- * Creates a new instance of KeyedHandler. The value of the first column
- * of each row will be a key in the Map.
- */
- public KeyedHandler() {
- this(ArrayHandler.ROW_PROCESSOR, 1, null);
- }
-
- /**
- * Creates a new instance of KeyedHandler. The value of the first column
- * of each row will be a key in the Map.
- *
- * @param convert The {@code RowProcessor} implementation
- * to use when converting rows into Maps
- */
- public KeyedHandler(final RowProcessor convert) {
- this(convert, 1, null);
- }
-
- /**
- * Creates a new instance of KeyedHandler.
- *
- * @param columnIndex The values to use as keys in the Map are
- * retrieved from the column at this index.
- */
- public KeyedHandler(final int columnIndex) {
- this(ArrayHandler.ROW_PROCESSOR, columnIndex, null);
- }
-
- /**
- * Creates a new instance of KeyedHandler.
- *
- * @param columnName The values to use as keys in the Map are
- * retrieved from the column with this name.
- */
- public KeyedHandler(final String columnName) {
- this(ArrayHandler.ROW_PROCESSOR, 1, columnName);
- }
-
- /** Private Helper
- * @param convert The {@code RowProcessor} implementation
- * to use when converting rows into Maps
- * @param columnIndex The values to use as keys in the Map are
- * retrieved from the column at this index.
- * @param columnName The values to use as keys in the Map are
- * retrieved from the column with this name.
- */
- private KeyedHandler(final RowProcessor convert, final int columnIndex,
- final String columnName) {
- this.convert = convert;
- this.columnIndex = columnIndex;
- this.columnName = columnName;
- }
- /**
- * This factory method is called by {@code handle()} to retrieve the
- * key value from the current {@code ResultSet} row. This
- * implementation returns {@code ResultSet.getObject()} for the
- * configured key column name or index.
- * @param rs ResultSet to create a key from
- * @return Object from the configured key column name/index
- *
- * @throws SQLException if a database access error occurs
- * @throws ClassCastException if the class datatype does not match the column type
- */
- // We assume that the user has picked the correct type to match the column
- // so getObject will return the appropriate type and the cast will succeed.
- @SuppressWarnings("unchecked")
- @Override
- protected K createKey(final ResultSet rs) throws SQLException {
- return (columnName == null) ?
- (K) rs.getObject(columnIndex) :
- (K) rs.getObject(columnName);
- }
-
- /**
- * This factory method is called by {@code handle()} to store the
- * current {@code ResultSet} row in some object. This
- * implementation returns a {@code Map} with case insensitive column
- * names as keys. Calls to {@code map.get("COL")} and
- * {@code map.get("col")} return the same value.
- * @param rs ResultSet to create a row from
- * @return Object typed Map containing column names to values
- * @throws SQLException if a database access error occurs
- */
- @Override
- protected Map<String, Object> createRow(final ResultSet rs) throws SQLException {
- return this.convert.toMap(rs);
- }
-
-}
+/*
+ * 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.handlers;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Map;
+
+import org.apache.commons.dbutils.RowProcessor;
+
+/**
+ * <p>
+ * {@code ResultSetHandler} implementation that returns a Map of Maps.
+ * {@code ResultSet} rows are converted into Maps which are then stored
+ * in a Map under the given key.
+ * </p>
+ * <p>
+ * If you had a Person table with a primary key column called ID, you could
+ * retrieve rows from the table like this:
+ * <pre>
+ * ResultSetHandler h = new KeyedHandler("id");
+ * Map found = (Map) queryRunner.query("select id, name, age from person", h);
+ * Map jane = (Map) found.get(new Long(1)); // jane's id is 1
+ * String janesName = (String) jane.get("name");
+ * Integer janesAge = (Integer) jane.get("age");
+ * </pre>
+ * Note that the "id" passed to KeyedHandler and "name" and "age" passed to the
+ * returned Map's get() method can be in any case. The data types returned for
+ * name and age are dependent upon how your JDBC driver converts SQL column
+ * types from the Person table into Java types.
+ * </p>
+ * <p>This class is thread safe.</p>
+ *
+ * @param <K> The type of the key
+ * @see org.apache.commons.dbutils.ResultSetHandler
+ * @since 1.1
+ */
+public class KeyedHandler<K> extends AbstractKeyedHandler<K, Map<String, Object>> {
+
+ /**
+ * The RowProcessor implementation to use when converting rows
+ * into Objects.
+ */
+ protected final RowProcessor convert;
+
+ /**
+ * The column index to retrieve key values from. Defaults to 1.
+ */
+ protected final int columnIndex;
+
+ /**
+ * The column name to retrieve key values from. Either columnName or
+ * columnIndex will be used but never both.
+ */
+ protected final String columnName;
+
+ /**
+ * Creates a new instance of KeyedHandler. The value of the first column
+ * of each row will be a key in the Map.
+ */
+ public KeyedHandler() {
+ this(ArrayHandler.ROW_PROCESSOR, 1, null);
+ }
+
+ /**
+ * Creates a new instance of KeyedHandler. The value of the first column
+ * of each row will be a key in the Map.
+ *
+ * @param convert The {@code RowProcessor} implementation
+ * to use when converting rows into Maps
+ */
+ public KeyedHandler(final RowProcessor convert) {
+ this(convert, 1, null);
+ }
+
+ /**
+ * Creates a new instance of KeyedHandler.
+ *
+ * @param columnIndex The values to use as keys in the Map are
+ * retrieved from the column at this index.
+ */
+ public KeyedHandler(final int columnIndex) {
+ this(ArrayHandler.ROW_PROCESSOR, columnIndex, null);
+ }
+
+ /**
+ * Creates a new instance of KeyedHandler.
+ *
+ * @param columnName The values to use as keys in the Map are
+ * retrieved from the column with this name.
+ */
+ public KeyedHandler(final String columnName) {
+ this(ArrayHandler.ROW_PROCESSOR, 1, columnName);
+ }
+
+ /** Private Helper
+ * @param convert The {@code RowProcessor} implementation
+ * to use when converting rows into Maps
+ * @param columnIndex The values to use as keys in the Map are
+ * retrieved from the column at this index.
+ * @param columnName The values to use as keys in the Map are
+ * retrieved from the column with this name.
+ */
+ private KeyedHandler(final RowProcessor convert, final int columnIndex,
+ final String columnName) {
+ this.convert = convert;
+ this.columnIndex = columnIndex;
+ this.columnName = columnName;
+ }
+ /**
+ * This factory method is called by {@code handle()} to retrieve the
+ * key value from the current {@code ResultSet} row. This
+ * implementation returns {@code ResultSet.getObject()} for the
+ * configured key column name or index.
+ * @param rs ResultSet to create a key from
+ * @return Object from the configured key column name/index
+ *
+ * @throws SQLException if a database access error occurs
+ * @throws ClassCastException if the class datatype does not match the column type
+ */
+ // We assume that the user has picked the correct type to match the column
+ // so getObject will return the appropriate type and the cast will succeed.
+ @SuppressWarnings("unchecked")
+ @Override
+ protected K createKey(final ResultSet rs) throws SQLException {
+ return (columnName == null) ?
+ (K) rs.getObject(columnIndex) :
+ (K) rs.getObject(columnName);
+ }
+
+ /**
+ * This factory method is called by {@code handle()} to store the
+ * current {@code ResultSet} row in some object. This
+ * implementation returns a {@code Map} with case insensitive column
+ * names as keys. Calls to {@code map.get("COL")} and
+ * {@code map.get("col")} return the same value.
+ * @param rs ResultSet to create a row from
+ * @return Object typed Map containing column names to values
+ * @throws SQLException if a database access error occurs
+ */
+ @Override
+ protected Map<String, Object> createRow(final ResultSet rs) throws SQLException {
+ return this.convert.toMap(rs);
+ }
+
+}