You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ws...@apache.org on 2013/02/26 04:52:38 UTC
svn commit: r1450009 [1/2] - in /commons/proper/dbutils/branches/2_0/src:
main/java/org/apache/commons/dbutils/ test/java/org/apache/commons/dbutils/
Author: wspeirs
Date: Tue Feb 26 03:52:37 2013
New Revision: 1450009
URL: http://svn.apache.org/r1450009
Log:
Major re-write of QueryRunner
- QueryRunner now returns Executors which provide a fluent API for binding parameters
- Parameters are bound by name instead of position
- AsyncQueryRunner runs an Executor
- Unit tests updated to match changes
**Update is NOT included yet, still working on the design of the Executors
Added:
commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/AbstractExecutor.java
commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/InsertExecutor.java
commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/QueryExecutor.java
commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/UpdateExecutor.java
commons/proper/dbutils/branches/2_0/src/test/java/org/apache/commons/dbutils/AbstractExecutorTest.java
commons/proper/dbutils/branches/2_0/src/test/java/org/apache/commons/dbutils/InsertExecutorTest.java
commons/proper/dbutils/branches/2_0/src/test/java/org/apache/commons/dbutils/QueryExecutorTest.java
commons/proper/dbutils/branches/2_0/src/test/java/org/apache/commons/dbutils/UpdateExecutorTest.java
Modified:
commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/AbstractQueryRunner.java
commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/AsyncQueryRunner.java
commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/QueryRunner.java
commons/proper/dbutils/branches/2_0/src/test/java/org/apache/commons/dbutils/AsyncQueryRunnerTest.java
commons/proper/dbutils/branches/2_0/src/test/java/org/apache/commons/dbutils/QueryRunnerTest.java
Added: commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/AbstractExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/AbstractExecutor.java?rev=1450009&view=auto
==============================================================================
--- commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/AbstractExecutor.java (added)
+++ commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/AbstractExecutor.java Tue Feb 26 03:52:37 2013
@@ -0,0 +1,249 @@
+/*
+ * 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.sql.Statement;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Abstract class for executing a query, insert, update, or batch.
+ *
+ * @since 2.0
+ * @author William Speirs <ws...@apache.org>
+ */
+abstract class AbstractExecutor<T extends AbstractExecutor<T>> {
+
+ private static final String COLON = ":"; // TODO: change this to any character
+
+ private final Connection conn;
+ private final String sql;
+ private final PreparedStatement stmt;
+
+ private final Map<String, List<Integer>> paramPosMap;
+ private final Map<String, Object> paramValueMap;
+ private Integer currentPosition = Integer.valueOf(0);
+
+ public AbstractExecutor(final Connection conn, final String sql) throws SQLException {
+ this.conn = conn;
+ this.sql = sql;
+ this.paramPosMap = new HashMap<String, List<Integer>>();
+ this.paramValueMap = new HashMap<String, Object>();
+
+ final Pattern paramPattern = Pattern.compile("(:\\w+)");
+ final Matcher matcher = paramPattern.matcher(sql);
+
+ // go through finding params
+ while(matcher.find()) {
+ insertParamPosition(matcher.group().replace(COLON, ""));
+ }
+
+ // replace all of the :names with ?, and create a prepared statement
+ stmt = conn.prepareStatement(sql.replaceAll(":\\w+", "\\?"));
+ }
+
+ /**
+ * Helper method to insert params and the current position into the map.
+ * @param param the SQL param.
+ */
+ private void insertParamPosition(final String param) {
+ List<Integer> posList = paramPosMap.get(param);
+
+ // create a new list if we need to
+ if(posList == null) {
+ posList = new ArrayList<Integer>();
+ paramPosMap.put(param, posList);
+ }
+
+ // increment first, so we match SQL numbering
+ posList.add(++currentPosition);
+ }
+
+ /**
+ * Gets the SQL statement that was passed into the constructor.
+ * @return the SQL statement passed into the constructor.
+ */
+ protected String getSql() {
+ return sql;
+ }
+
+ /**
+ * Returns the underlying prepared statement.
+ * @return the underlying prepared statement.
+ */
+ protected PreparedStatement getStatement() {
+ return stmt;
+ }
+
+ /**
+ * Returns the underlying connection.
+ * @return the underlying connection.
+ */
+ protected Connection getConnection() {
+ return conn;
+ }
+
+ /**
+ * Throws an exception if there are unmapped params.
+ * @throws SQLException if there are unmapped params.
+ */
+ protected void throwIfUnmappedParams() throws SQLException {
+ if(paramPosMap.size() != 0) {
+ final Set<String> unmappedParams = paramPosMap.keySet();
+ final StringBuilder sb = new StringBuilder("There are unbound parameters: ");
+
+ for(String param:unmappedParams) {
+ sb.append(param);
+ sb.append(", ");
+ }
+
+ // remove the last comma
+ sb.delete(sb.length()-2, sb.length());
+
+ // throw our exception
+ throw new SQLException(sb.toString());
+ }
+ }
+
+ /**
+ * Binds a named parameter to a value.
+ *
+ * @param name the name of the parameter in the SQL statement.
+ * @param value the value of the parameter in the SQL statement.
+ * @return this execution object to provide the fluent style.
+ * @throws SQLException thrown if the parameter is not found, already bound, or there is an issue binding it.
+ */
+ public T bind(String name, final Object value) throws SQLException {
+ name = name.replace(COLON, ""); // so we can take ":name" or "name"
+
+ final List<Integer> pos = paramPosMap.remove(name);
+
+ if(pos == null) {
+ throw new SQLException(name + " is either not found in the SQL statement, or was already bound");
+ }
+
+ // go through and bind all of the positions for this name
+ for(Integer p:pos) {
+ // TODO: need to figure out how to bind NULL
+ stmt.setObject(p, value);
+ }
+
+ // add the param and value to our map
+ paramValueMap.put(name, value);
+
+ // suppressed because the casting will always work here
+ @SuppressWarnings("unchecked")
+ final T ret = (T) this;
+
+ return ret;
+ }
+
+ /**
+ * 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.
+ *
+ * @throws SQLException if a database access error occurs
+ */
+ protected void rethrow(SQLException cause) throws SQLException {
+
+ String causeMessage = cause.getMessage();
+
+ if (causeMessage == null) {
+ causeMessage = "";
+ }
+
+ final StringBuffer msg = new StringBuffer(causeMessage);
+
+ msg.append(" Query: ");
+ msg.append(sql);
+ msg.append(" Parameters: ");
+
+ // loop through adding the parameter to value mappings
+ for(Map.Entry<String, Object> param:paramValueMap.entrySet()) {
+ msg.append(param.getKey());
+ msg.append("=");
+ msg.append(param.getValue());
+ msg.append(" ");
+ }
+
+ final SQLException e = new SQLException(msg.toString(), cause.getSQLState(), cause.getErrorCode());
+ e.setNextException(cause);
+
+ throw e;
+ }
+
+ /**
+ * Wrap the <code>ResultSet</code> in a decorator before processing it. This
+ * implementation returns the <code>ResultSet</code> it is given without any
+ * decoration.
+ *
+ * @param rs The <code>ResultSet</code> to decorate; never <code>null</code>.
+ * @return The <code>ResultSet</code> wrapped in some decorator.
+ */
+ protected ResultSet wrap(ResultSet rs) {
+ return rs;
+ }
+
+ /**
+ * Close a <code>Connection</code>. This implementation avoids closing if
+ * null and does <strong>not</strong> suppress any exceptions. Subclasses
+ * can override to provide special handling like logging.
+ *
+ * @param conn Connection to close
+ * @throws SQLException if a database access error occurs
+ */
+ protected void close(Connection conn) throws SQLException {
+ DbUtils.close(conn);
+ }
+
+ /**
+ * Close a <code>Statement</code>. This implementation avoids closing if
+ * null and does <strong>not</strong> suppress any exceptions. Subclasses
+ * can override to provide special handling like logging.
+ *
+ * @param stmt Statement to close
+ * @throws SQLException if a database access error occurs
+ */
+ protected void close(Statement stmt) throws SQLException {
+ DbUtils.close(stmt);
+ }
+
+ /**
+ * Close a <code>ResultSet</code>. This implementation avoids closing if
+ * null and does <strong>not</strong> suppress any exceptions. Subclasses
+ * can override to provide special handling like logging.
+ *
+ * @param rs ResultSet to close
+ * @throws SQLException if a database access error occurs
+ */
+ protected void close(ResultSet rs) throws SQLException {
+ DbUtils.close(rs);
+ }
+
+
+}
Modified: commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/AbstractQueryRunner.java
URL: http://svn.apache.org/viewvc/commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/AbstractQueryRunner.java?rev=1450009&r1=1450008&r2=1450009&view=diff
==============================================================================
--- commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/AbstractQueryRunner.java (original)
+++ commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/AbstractQueryRunner.java Tue Feb 26 03:52:37 2013
@@ -16,35 +16,16 @@
*/
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.Connection;
-import java.sql.ParameterMetaData;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
import java.sql.SQLException;
-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.
*/
private final DataSource ds;
@@ -57,53 +38,17 @@ public abstract class AbstractQueryRunne
}
/**
- * Constructor to control the use of <code>ParameterMetaData</code>.
- *
- * @param pmdKnownBroken
- * Some drivers don't support
- * {@link ParameterMetaData#getParameterType(int) }; if
- * <code>pmdKnownBroken</code> is set to true, we won't even try
- * it; if false, we'll try it, and if it breaks, we'll remember
- * not to use it again.
- */
- public AbstractQueryRunner(boolean pmdKnownBroken) {
- this.pmdKnownBroken = pmdKnownBroken;
- ds = null;
- }
-
- /**
* Constructor to provide a <code>DataSource</code>. Methods that do not
* take a <code>Connection</code> parameter will retrieve connections from
* this <code>DataSource</code>.
*
- * @param ds
- * The <code>DataSource</code> to retrieve connections from.
+ * @param ds The <code>DataSource</code> to retrieve connections from.
*/
public AbstractQueryRunner(DataSource ds) {
this.ds = ds;
}
/**
- * Constructor to provide a <code>DataSource</code> and control the use of
- * <code>ParameterMetaData</code>. Methods that do not take a
- * <code>Connection</code> parameter will retrieve connections from this
- * <code>DataSource</code>.
- *
- * @param ds
- * The <code>DataSource</code> to retrieve connections from.
- * @param pmdKnownBroken
- * Some drivers don't support
- * {@link ParameterMetaData#getParameterType(int) }; if
- * <code>pmdKnownBroken</code> is set to true, we won't even try
- * it; if false, we'll try it, and if it breaks, we'll remember
- * not to use it again.
- */
- public AbstractQueryRunner(DataSource ds, boolean pmdKnownBroken) {
- this.pmdKnownBroken = pmdKnownBroken;
- this.ds = ds;
- }
-
- /**
* Returns the <code>DataSource</code> this runner is using.
* <code>QueryRunner</code> methods always call this method to get the
* <code>DataSource</code> so subclasses can provide specialized behavior.
@@ -115,44 +60,6 @@ public abstract class AbstractQueryRunne
}
/**
- * Some drivers don't support
- * {@link ParameterMetaData#getParameterType(int) }; if
- * <code>pmdKnownBroken</code> is set to true, we won't even try it; if
- * false, we'll try it, and if it breaks, we'll remember not to use it
- * again.
- *
- * @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>PreparedStatement</code> object for the given SQL.
- * <code>QueryRunner</code> methods always call this method to prepare
- * statements for them. Subclasses can override this method to provide
- * special PreparedStatement configuration if needed. This implementation
- * simply calls <code>conn.prepareStatement(sql)</code>.
- *
- * @param conn
- * The <code>Connection</code> used to create the
- * <code>PreparedStatement</code>
- * @param sql
- * The SQL statement to prepare.
- * @return An initialized <code>PreparedStatement</code>.
- * @throws SQLException
- * if a database access error occurs
- */
- protected PreparedStatement prepareStatement(Connection conn, String sql)
- throws SQLException {
-
- return conn.prepareStatement(sql);
- }
-
- /**
* Factory method that creates and initializes a <code>Connection</code>
* object. <code>QueryRunner</code> methods always call this method to
* retrieve connections from its DataSource. Subclasses can override this
@@ -160,9 +67,7 @@ public abstract class AbstractQueryRunne
* needed. This implementation simply calls <code>ds.getConnection()</code>.
*
* @return An initialized <code>Connection</code>.
- * @throws SQLException
- * if a database access error occurs
- * @since DbUtils 1.1
+ * @throws SQLException if a database access error occurs
*/
protected Connection prepareConnection() throws SQLException {
if (this.getDataSource() == null) {
@@ -175,78 +80,18 @@ public abstract class AbstractQueryRunne
/**
* Fill the <code>PreparedStatement</code> replacement parameters with the
- * given objects.
- *
- * @param stmt
- * PreparedStatement to fill
- * @param params
- * Query replacement parameters; <code>null</code> is a valid
- * value to pass in.
- * @throws SQLException
- * if a database access error occurs
- */
- public void fillStatement(PreparedStatement stmt, Object... params)
- throws SQLException {
-
- // check the parameter count, if we can
- ParameterMetaData pmd = null;
- if (!pmdKnownBroken) {
- pmd = stmt.getParameterMetaData();
- int stmtCount = pmd.getParameterCount();
- int paramsCount = params == null ? 0 : params.length;
-
- if (stmtCount != paramsCount) {
- throw new SQLException("Wrong number of parameters: expected "
- + stmtCount + ", was given " + paramsCount);
- }
- }
-
- // nothing to do here
- if (params == null) {
- return;
- }
-
- for (int i = 0; i < params.length; i++) {
- if (params[i] != null) {
- 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) {
- 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 (SQLException e) {
- pmdKnownBroken = true;
- }
- }
- stmt.setNull(i + 1, sqlType);
- }
- }
- }
-
- /**
- * Fill the <code>PreparedStatement</code> replacement parameters with the
* given object's bean property values.
*
- * @param stmt
- * PreparedStatement to fill
- * @param bean
- * a JavaBean object
- * @param 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(PreparedStatement stmt, Object bean,
- PropertyDescriptor[] properties) throws SQLException {
+ * @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(PreparedStatement stmt,
+ Object bean,
+ PropertyDescriptor[] properties) throws SQLException {
Object[] params = new Object[properties.length];
for (int i = 0; i < properties.length; i++) {
PropertyDescriptor property = properties[i];
@@ -272,6 +117,7 @@ public abstract class AbstractQueryRunne
}
fillStatement(stmt, params);
}
+*/
/**
* Fill the <code>PreparedStatement</code> replacement parameters with the
@@ -288,6 +134,7 @@ public abstract class AbstractQueryRunne
* @throws SQLException
* If a database access error occurs
*/
+/*
public void fillStatementWithBean(PreparedStatement stmt, Object bean,
String... propertyNames) throws SQLException {
PropertyDescriptor[] descriptors;
@@ -321,120 +168,18 @@ public abstract class AbstractQueryRunne
}
fillStatementWithBean(stmt, bean, sorted);
}
-
- /**
- * 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</code> is a valid
- * value to pass in.
- *
- * @throws SQLException
- * if a database access error occurs
- */
- protected void rethrow(SQLException cause, String sql, Object... params)
- throws SQLException {
-
- String causeMessage = cause.getMessage();
- if (causeMessage == null) {
- causeMessage = "";
- }
- StringBuffer msg = new StringBuffer(causeMessage);
-
- msg.append(" Query: ");
- msg.append(sql);
- msg.append(" Parameters: ");
-
- if (params == null) {
- msg.append("[]");
- } else {
- msg.append(Arrays.deepToString(params));
- }
-
- SQLException e = new SQLException(msg.toString(), cause.getSQLState(),
- cause.getErrorCode());
- e.setNextException(cause);
-
- throw e;
- }
-
- /**
- * Wrap the <code>ResultSet</code> in a decorator before processing it. This
- * implementation returns the <code>ResultSet</code> it is given without any
- * decoration.
- *
- * <p>
- * Often, the implementation of this method can be done in an anonymous
- * inner class like this:
- * </p>
- *
- * <pre>
- * QueryRunner run = new QueryRunner() {
- * protected ResultSet wrap(ResultSet rs) {
- * return StringTrimmedResultSet.wrap(rs);
- * }
- * };
- * </pre>
- *
- * @param rs
- * The <code>ResultSet</code> to decorate; never
- * <code>null</code>.
- * @return The <code>ResultSet</code> wrapped in some decorator.
- */
- protected ResultSet wrap(ResultSet rs) {
- return rs;
- }
-
+*/
+
/**
* Close a <code>Connection</code>. This implementation avoids closing if
* null and does <strong>not</strong> suppress any exceptions. Subclasses
* can override to provide special handling like logging.
*
- * @param conn
- * Connection to close
- * @throws SQLException
- * if a database access error occurs
- * @since DbUtils 1.1
+ * @param conn Connection to close
+ * @throws SQLException if a database access error occurs
*/
protected void close(Connection conn) throws SQLException {
DbUtils.close(conn);
}
- /**
- * Close a <code>Statement</code>. This implementation avoids closing if
- * null and does <strong>not</strong> suppress any exceptions. Subclasses
- * can override to provide special handling like logging.
- *
- * @param stmt
- * Statement to close
- * @throws SQLException
- * if a database access error occurs
- * @since DbUtils 1.1
- */
- protected void close(Statement stmt) throws SQLException {
- DbUtils.close(stmt);
- }
-
- /**
- * Close a <code>ResultSet</code>. This implementation avoids closing if
- * null and does <strong>not</strong> suppress any exceptions. Subclasses
- * can override to provide special handling like logging.
- *
- * @param rs
- * ResultSet to close
- * @throws SQLException
- * if a database access error occurs
- * @since DbUtils 1.1
- */
- protected void close(ResultSet rs) throws SQLException {
- DbUtils.close(rs);
- }
-
}
Modified: commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/AsyncQueryRunner.java
URL: http://svn.apache.org/viewvc/commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/AsyncQueryRunner.java?rev=1450009&r1=1450008&r2=1450009&view=diff
==============================================================================
--- commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/AsyncQueryRunner.java (original)
+++ commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/AsyncQueryRunner.java Tue Feb 26 03:52:37 2013
@@ -16,364 +16,82 @@
*/
package org.apache.commons.dbutils;
-import java.sql.Connection;
import java.sql.SQLException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
/**
- * Executes SQL queries with pluggable strategies for handling
- * <code>ResultSet</code>s. This class is thread safe.
+ * Convenience class for executing QueryExecutor, InsertExecutor, or UpdateExecutors asynchronously.
*
- * @see ResultSetHandler
- * @since 1.4
+ * @author William Speirs <ws...@apache.org>
+ * @since 2.0
*/
-public class AsyncQueryRunner extends AbstractQueryRunner {
+public class AsyncQueryRunner {
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(ExecutorService executorService, QueryRunner queryRunner) {
+ public AsyncQueryRunner(ExecutorService executorService) {
this.executorService = executorService;
- this.queryRunner = queryRunner;
}
/**
- * Execute a batch of SQL INSERT, UPDATE, or DELETE queries.
- *
- * @param conn The <code>Connection</code> 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</code> 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</code> is retrieved from the <code>DataSource</code>
- * set in the constructor. This <code>Connection</code> 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</code> 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);
- }
-
- });
- }
-
- /**
- * 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</code> 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</code> 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</code> is retrieved from the
- * <code>DataSource</code> set in the constructor.
+ * Execute a {@link org.apache.commons.dbutils.QueryExecutor} given a handler.
* @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</code>.
- * @param params Initialize the PreparedStatement's IN parameters with
- * this array.
+ * @param handler The handler that converts the results into an object.
* @return A <code>Future</code> which returns the result of the query call.
* @throws SQLException if a database access error occurs
*/
- public <T> Future<T> query(final String sql, final ResultSetHandler<T> rsh, final Object... params) throws SQLException {
+ public <T> Future<T> query(final QueryExecutor executor, final ResultSetHandler<T> handler) throws SQLException {
return executorService.submit(new Callable<T>() {
@Override
public T call() throws Exception {
- return queryRunner.query(sql, rsh, params);
+ return executor.query(handler);
}
});
}
/**
- * Executes the given SELECT SQL without any replacement parameters.
- * The <code>Connection</code> is retrieved from the
- * <code>DataSource</code> set in the constructor.
+ * Execute a {@link org.apache.commons.dbutils.UpdateExecutor} given a handler.
* @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</code>.
- *
* @return A <code>Future</code> which returns the result of the query call.
* @throws SQLException if a database access error occurs
*/
- public <T> Future<T> query(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);
- }
-
- });
- }
-
- /**
- * 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</code> 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 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</code> 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 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</code> 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 queryRunner.update(conn, sql, params);
- }
-
- });
- }
-
- /**
- * Executes the given INSERT, UPDATE, or DELETE SQL statement without
- * any replacement parameters. The <code>Connection</code> is retrieved
- * from the <code>DataSource</code> set in the constructor. This
- * <code>Connection</code> 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</code> which returns the number of rows updated.
- */
- public Future<Integer> update(final String sql) throws SQLException {
+ public Future<Integer> update(final UpdateExecutor executor) throws SQLException {
return executorService.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
- return queryRunner.update(sql);
+ return executor.update();
}
});
}
/**
- * Executes the given INSERT, UPDATE, or DELETE SQL statement with
- * a single replacement parameter. The <code>Connection</code> is
- * retrieved from the <code>DataSource</code> set in the constructor.
- * This <code>Connection</code> 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</code> 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 queryRunner.update(sql, param);
- }
-
- });
- }
-
- /**
- * Executes the given INSERT, UPDATE, or DELETE SQL statement. The
- * <code>Connection</code> is retrieved from the <code>DataSource</code>
- * set in the constructor. This <code>Connection</code> 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.
+ * Execute a {@link org.apache.commons.dbutils.InsertExecutor} given a handler.
+ * @param <T> The type of object that the handler returns
+ * @param handler The handler that converts the results into an object.
+ * @return A <code>Future</code> which returns the result of the query call.
* @throws SQLException if a database access error occurs
- * @return A <code>Future</code> 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 queryRunner.update(sql, params);
- }
-
- });
- }
-
- /**
- * Executes {@link QueryRunner#insert(String, ResultSetHandler)} asynchronously.
- *
- * @see QueryRunner#insert(String, ResultSetHandler)
- * @since 1.6
*/
- public <T> Future<T> insert(final String sql, final ResultSetHandler<T> rsh) throws SQLException {
+ public <T> Future<T> insert(final InsertExecutor executor, final ResultSetHandler<T> handler) throws SQLException {
return executorService.submit(new Callable<T>() {
@Override
public T call() throws Exception {
- return queryRunner.insert(sql, rsh);
+ return executor.insert(handler);
}
});
}
- /**
- * Executes {@link QueryRunner#insert(String, ResultSetHandler, Object...)} asynchronously.
- *
- * @see QueryRunner#insert(String, ResultSetHandler, Object...)
- * @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.
- *
- * @see QueryRunner#insert(Connection, String, ResultSetHandler)
- * @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.
- *
- * @see QueryRunner#insert(Connection, String, ResultSetHandler, Object...)
- * @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);
- }
- });
- }
-
}
Added: commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/InsertExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/InsertExecutor.java?rev=1450009&view=auto
==============================================================================
--- commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/InsertExecutor.java (added)
+++ commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/InsertExecutor.java Tue Feb 26 03:52:37 2013
@@ -0,0 +1,76 @@
+/*
+ * 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.ResultSet;
+import java.sql.SQLException;
+
+
+public class InsertExecutor extends AbstractExecutor<InsertExecutor> {
+
+ private final boolean closeConn;
+
+ public InsertExecutor(final Connection conn, final String sql, final boolean closeConnection) throws SQLException {
+ super(conn, sql);
+ this.closeConn = closeConnection;
+ }
+
+ /**
+ * Executes the given INSERT SQL statement.
+ *
+ * @param handler The handler used to create the result object from
+ * the <code>ResultSet</code> of auto-generated keys.
+ *
+ * @return An object generated by the handler.
+ * @throws SQLException If there are database or parameter errors.
+ */
+ public <T> T insert(ResultSetHandler<T> handler) throws SQLException {
+ // throw an exception if there are unmapped parameters
+ this.throwIfUnmappedParams();
+
+ // make sure our handler is not null
+ if (handler == null) {
+ if (closeConn) {
+ close(getConnection());
+ }
+ throw new SQLException("Null ResultSetHandler");
+ }
+
+ try {
+ // execute the update
+ getStatement().executeUpdate();
+
+ // get the result set
+ final ResultSet resultSet = getStatement().getGeneratedKeys();
+
+ // run the handler over the results and return them
+ return handler.handle(resultSet);
+ } catch (SQLException e) {
+ this.rethrow(e);
+ } finally {
+ close(getStatement());
+ if (closeConn) {
+ close(getConnection());
+ }
+ }
+
+ // we get here only if something is thrown
+ return null;
+ }
+
+}
Added: commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/QueryExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/QueryExecutor.java?rev=1450009&view=auto
==============================================================================
--- commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/QueryExecutor.java (added)
+++ commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/QueryExecutor.java Tue Feb 26 03:52:37 2013
@@ -0,0 +1,82 @@
+/*
+ * 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.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * Fluent class for executing a query.
+ *
+ * @since 2.0
+ * @author William Speirs <ws...@apache.org>
+ */
+class QueryExecutor extends AbstractExecutor<QueryExecutor> {
+
+ private final boolean closeConn;
+
+ public QueryExecutor(final Connection conn, final String sql, final boolean closeConnection) throws SQLException {
+ super(conn, sql);
+ this.closeConn = closeConnection;
+ }
+
+ /**
+ * Calls query after checking the parameters to ensure nothing is null.
+ *
+ * @param rsh The handler that converts the results into an object.
+ *
+ * @return The results of the query.
+ * @throws SQLException If there are database or parameter errors.
+ */
+ public <T> T query(ResultSetHandler<T> handler) throws SQLException {
+ // throw an exception if there are unmapped parameters
+ this.throwIfUnmappedParams();
+
+ // make sure our handler is not null
+ if (handler == null) {
+ if (closeConn) {
+ close(getConnection());
+ }
+ throw new SQLException("Null ResultSetHandler");
+ }
+
+ ResultSet resultSet = null;
+
+ try {
+ // execute the query, wrapping it
+ resultSet = this.wrap(getStatement().executeQuery());
+ // execute the handler
+ return handler.handle(resultSet);
+ } catch (SQLException e) {
+ // rethrow our exception printing more information
+ this.rethrow(e);
+ } finally {
+ try {
+ close(resultSet);
+ } finally {
+ close(getStatement());
+ if (closeConn) {
+ close(getConnection());
+ }
+ }
+ }
+
+ // we get here only if something is thrown
+ return null;
+ }
+}
Modified: commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/QueryRunner.java
URL: http://svn.apache.org/viewvc/commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/QueryRunner.java?rev=1450009&r1=1450008&r2=1450009&view=diff
==============================================================================
--- commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/QueryRunner.java (original)
+++ commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/QueryRunner.java Tue Feb 26 03:52:37 2013
@@ -17,11 +17,7 @@
package org.apache.commons.dbutils;
import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
import java.sql.SQLException;
-import java.sql.Statement;
-
import javax.sql.DataSource;
/**
@@ -40,17 +36,6 @@ public class QueryRunner extends Abstrac
}
/**
- * Constructor for QueryRunner that controls the use of <code>ParameterMetaData</code>.
- *
- * @param pmdKnownBroken Some drivers don't support {@link java.sql.ParameterMetaData#getParameterType(int) };
- * if <code>pmdKnownBroken</code> is set to true, we won't even try it; if false, we'll try it,
- * and if it breaks, we'll remember not to use it again.
- */
- public QueryRunner(boolean pmdKnownBroken) {
- super(pmdKnownBroken);
- }
-
- /**
* Constructor for QueryRunner that takes a <code>DataSource</code> to use.
*
* Methods that do not take a <code>Connection</code> parameter will retrieve connections from this
@@ -63,20 +48,6 @@ public class QueryRunner extends Abstrac
}
/**
- * Constructor for QueryRunner that takes a <code>DataSource</code> and controls the use of <code>ParameterMetaData</code>.
- * Methods that do not take a <code>Connection</code> parameter will retrieve connections from this
- * <code>DataSource</code>.
- *
- * @param ds The <code>DataSource</code> to retrieve connections from.
- * @param pmdKnownBroken Some drivers don't support {@link java.sql.ParameterMetaData#getParameterType(int) };
- * if <code>pmdKnownBroken</code> is set to true, we won't even try it; if false, we'll try it,
- * and if it breaks, we'll remember not to use it again.
- */
- public QueryRunner(DataSource ds, boolean pmdKnownBroken) {
- super(ds, pmdKnownBroken);
- }
-
- /**
* Execute a batch of SQL INSERT, UPDATE, or DELETE queries.
*
* @param conn The Connection to use to run the query. The caller is
@@ -122,6 +93,8 @@ public class QueryRunner extends Abstrac
* @throws SQLException If there are database or parameter errors.
*/
private int[] batch(Connection conn, boolean closeConn, String sql, Object[][] params) throws SQLException {
+ throw new SQLException("Not yet implemented");
+/*
if (conn == null) {
throw new SQLException("Null connection");
}
@@ -161,86 +134,46 @@ public class QueryRunner extends Abstrac
}
return rows;
+*/
}
/**
- * Execute an SQL SELECT query with replacement parameters. The
- * caller is responsible for closing the connection.
- * @param <T> The type of object that the handler returns
- * @param conn The connection to execute the query in.
- * @param sql The query to execute.
- * @param rsh The handler that converts the results into an object.
- * @param params The replacement parameters.
- * @return The object returned by the handler.
- * @throws SQLException if a database access error occurs
- */
- public <T> T query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException {
- return this.<T>query(conn, false, sql, rsh, params);
- }
-
- /**
- * Execute an SQL SELECT query without any replacement parameters. The
- * caller is responsible for closing the connection.
- * @param <T> The type of object that the handler returns
- * @param conn The connection to execute the query in.
- * @param sql The query to execute.
- * @param rsh The handler that converts the results into an object.
- * @return The object returned by the handler.
- * @throws SQLException if a database access error occurs
- */
- public <T> T query(Connection conn, String sql, ResultSetHandler<T> rsh) throws SQLException {
- return this.<T>query(conn, false, sql, rsh, (Object[]) null);
- }
-
- /**
- * Executes the given SELECT SQL query and returns a result object.
+ * Creates an {@link org.apache.commons.dbutils.QueryExecutor} for the given SQL statement.
* The <code>Connection</code> is retrieved from the
* <code>DataSource</code> 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</code>.
- * @param params Initialize the PreparedStatement's IN parameters with
- * this array.
- * @return An object generated by the handler.
- * @throws SQLException if a database access error occurs
+ * @return An {@link org.apache.commons.dbutils.QueryExecutor} for this SQL statement.
+ * @throws SQLException If there are database or parameter errors.
*/
- public <T> T query(String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException {
+ public QueryExecutor query(String sql) throws SQLException {
Connection conn = this.prepareConnection();
- return this.<T>query(conn, true, sql, rsh, params);
+ return this.query(conn, true, sql);
}
/**
- * Executes the given SELECT SQL without any replacement parameters.
- * The <code>Connection</code> is retrieved from the
- * <code>DataSource</code> set in the constructor.
- * @param <T> The type of object that the handler returns
+ * Creates an {@link org.apache.commons.dbutils.QueryExecutor} for the given SQL statement and connection.
+ * The connection is <b>NOT</b> closed after execution.
+ * @param conn The connection to use for the update call.
* @param sql The SQL statement to execute.
- * @param rsh The handler used to create the result object from
- * the <code>ResultSet</code>.
- *
- * @return An object generated by the handler.
- * @throws SQLException if a database access error occurs
+ * @return An {@link org.apache.commons.dbutils.QueryExecutor} for this SQL statement.
+ * @throws SQLException If there are database or parameter errors.
*/
- public <T> T query(String sql, ResultSetHandler<T> rsh) throws SQLException {
- Connection conn = this.prepareConnection();
+ public QueryExecutor query(Connection con, String sql) throws SQLException {
+ final Connection conn = this.prepareConnection();
- return this.<T>query(conn, true, sql, rsh, (Object[]) null);
+ return this.query(conn, true, sql);
}
/**
- * Calls query after checking the parameters to ensure nothing is null.
- * @param conn The connection to use for the query call.
+ * Creates an {@link org.apache.commons.dbutils.QueryExecutor} for the given SQL statement and connection.
+ * @param conn The connection to use for the update call.
* @param closeConn True if the connection should be closed, false otherwise.
* @param sql The SQL statement to execute.
- * @param params An array of query replacement parameters. Each row in
- * this array is one set of batch replacement values.
- * @return The results of the query.
+ * @return An {@link org.apache.commons.dbutils.QueryExecutor} for this SQL statement.
* @throws SQLException If there are database or parameter errors.
*/
- private <T> T query(Connection conn, boolean closeConn, String sql, ResultSetHandler<T> rsh, Object... params)
- throws SQLException {
+ public QueryExecutor query(Connection conn, boolean closeConn, String sql) throws SQLException {
if (conn == null) {
throw new SQLException("Null connection");
}
@@ -251,145 +184,47 @@ public class QueryRunner extends Abstrac
}
throw new SQLException("Null SQL statement");
}
-
- if (rsh == null) {
- if (closeConn) {
- close(conn);
- }
- throw new SQLException("Null ResultSetHandler");
- }
-
- PreparedStatement stmt = null;
- ResultSet rs = null;
- T result = null;
-
- try {
- stmt = this.prepareStatement(conn, sql);
- this.fillStatement(stmt, params);
- rs = this.wrap(stmt.executeQuery());
- result = rsh.handle(rs);
-
- } catch (SQLException e) {
- this.rethrow(e, sql, params);
-
- } finally {
- try {
- close(rs);
- } finally {
- close(stmt);
- if (closeConn) {
- close(conn);
- }
- }
- }
-
- return result;
- }
-
- /**
- * Execute an SQL INSERT, UPDATE, or DELETE query without replacement
- * parameters.
- *
- * @param conn The connection to use to run the query.
- * @param sql The SQL to execute.
- * @return The number of rows updated.
- * @throws SQLException if a database access error occurs
- */
- public int update(Connection conn, String sql) throws SQLException {
- return this.update(conn, false, sql, (Object[]) null);
- }
-
- /**
- * Execute an SQL INSERT, UPDATE, or DELETE query with a single replacement
- * parameter.
- *
- * @param conn The connection to use to run the query.
- * @param sql The SQL to execute.
- * @param param The replacement parameter.
- * @return The number of rows updated.
- * @throws SQLException if a database access error occurs
- */
- public int update(Connection conn, String sql, Object param) throws SQLException {
- return this.update(conn, false, sql, new Object[]{param});
- }
-
- /**
- * Execute an SQL INSERT, UPDATE, or DELETE query.
- *
- * @param conn The connection to use to run the query.
- * @param sql The SQL to execute.
- * @param params The query replacement parameters.
- * @return The number of rows updated.
- * @throws SQLException if a database access error occurs
- */
- public int update(Connection conn, String sql, Object... params) throws SQLException {
- return update(conn, false, sql, params);
- }
-
- /**
- * Executes the given INSERT, UPDATE, or DELETE SQL statement without
- * any replacement parameters. The <code>Connection</code> is retrieved
- * from the <code>DataSource</code> set in the constructor. This
- * <code>Connection</code> must be in auto-commit mode or the update will
- * not be saved.
- *
- * @param sql The SQL statement to execute.
- * @throws SQLException if a database access error occurs
- * @return The number of rows updated.
- */
- public int update(String sql) throws SQLException {
- Connection conn = this.prepareConnection();
-
- return this.update(conn, true, sql, (Object[]) null);
+
+ return new QueryExecutor(conn, sql, closeConn);
}
/**
- * Executes the given INSERT, UPDATE, or DELETE SQL statement with
- * a single replacement parameter. The <code>Connection</code> is
- * retrieved from the <code>DataSource</code> set in the constructor.
- * This <code>Connection</code> must be in auto-commit mode or the
- * update will not be saved.
+ * Creates an {@link org.apache.commons.dbutils.UpdateExecutor} for the given SQL statement.
+ * <code>Connection</code> is retrieved from the <code>DataSource</code>
+ * set in the constructor. This <code>Connection</code> 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.
+ * @return An {@link org.apache.commons.dbutils.UpdateExecutor} for this SQL statement.
* @throws SQLException if a database access error occurs
- * @return The number of rows updated.
*/
- public int update(String sql, Object param) throws SQLException {
+ public UpdateExecutor update(String sql) throws SQLException {
Connection conn = this.prepareConnection();
- return this.update(conn, true, sql, new Object[]{param});
+ return this.update(conn, true, sql);
}
/**
- * Executes the given INSERT, UPDATE, or DELETE SQL statement. The
- * <code>Connection</code> is retrieved from the <code>DataSource</code>
- * set in the constructor. This <code>Connection</code> must be in
- * auto-commit mode or the update will not be saved.
- *
+ * Creates an {@link org.apache.commons.dbutils.UpdateExecutor} for the given SQL statement and connection.
+ * The connection is <b>NOT</b> closed after execution.
+ * @param conn The connection to use for the update call.
* @param sql The SQL statement to execute.
- * @param params Initializes the PreparedStatement's IN (i.e. '?')
- * parameters.
- * @throws SQLException if a database access error occurs
- * @return The number of rows updated.
+ * @return An {@link org.apache.commons.dbutils.UpdateExecutor} for this SQL statement.
+ * @throws SQLException If there are database or parameter errors.
*/
- public int update(String sql, Object... params) throws SQLException {
- Connection conn = this.prepareConnection();
-
- return this.update(conn, true, sql, params);
+ public UpdateExecutor update(Connection conn, String sql) throws SQLException {
+ return this.update(conn, false, sql);
}
/**
- * Calls update after checking the parameters to ensure nothing is null.
+ * Creates an {@link org.apache.commons.dbutils.UpdateExecutor} for the given SQL statement and connection.
* @param conn The connection to use for the update call.
* @param closeConn True if the connection should be closed, false otherwise.
* @param sql The SQL statement to execute.
- * @param params An array of update replacement parameters. Each row in
- * this array is one set of update replacement values.
- * @return The number of rows updated.
+ * @return An {@link org.apache.commons.dbutils.UpdateExecutor} for this SQL statement.
* @throws SQLException If there are database or parameter errors.
*/
- private int update(Connection conn, boolean closeConn, String sql, Object... params) throws SQLException {
+ public UpdateExecutor update(Connection conn, boolean closeConn, String sql) throws SQLException {
if (conn == null) {
throw new SQLException("Null connection");
}
@@ -401,105 +236,47 @@ public class QueryRunner extends Abstrac
throw new SQLException("Null SQL statement");
}
- PreparedStatement stmt = null;
- int rows = 0;
-
- try {
- stmt = this.prepareStatement(conn, sql);
- this.fillStatement(stmt, params);
- rows = stmt.executeUpdate();
-
- } catch (SQLException e) {
- this.rethrow(e, sql, params);
-
- } finally {
- close(stmt);
- if (closeConn) {
- close(conn);
- }
- }
-
- return rows;
+ return new UpdateExecutor(conn, sql, closeConn);
}
/**
- * Executes the given INSERT SQL without any replacement parameters.
- * The <code>Connection</code> is retrieved from the
- * <code>DataSource</code> 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</code> of auto-generated keys.
- * @return An object generated by the handler.
- * @throws SQLException if a database access error occurs
- * @since 1.6
- */
- public <T> T insert(String sql, ResultSetHandler<T> rsh) throws SQLException {
- return insert(this.prepareConnection(), true, sql, rsh, (Object[]) null);
- }
-
- /**
- * Executes the given INSERT SQL statement. The
+ * Creates an {@link org.apache.commons.dbutils.InsertExecutor} for the given SQL.
* <code>Connection</code> is retrieved from the <code>DataSource</code>
* set in the constructor. This <code>Connection</code> must be in
* auto-commit mode or the insert will not be saved.
- * @param <T> The type of object that the handler returns
+ * @param conn The connection to use for the query call.
* @param sql The SQL statement to execute.
- * @param rsh The handler used to create the result object from
- * the <code>ResultSet</code> of auto-generated keys.
- * @param params Initializes the PreparedStatement's IN (i.e. '?')
- * @return An object generated by the handler.
- * @throws SQLException if a database access error occurs
- * @since 1.6
- */
- public <T> T insert(String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException {
- return insert(this.prepareConnection(), true, sql, rsh, params);
- }
-
- /**
- * Execute an SQL INSERT query without replacement parameters.
- * @param <T> The type of object that the handler returns
- * @param conn The connection to use to run the query.
- * @param sql The SQL to execute.
- * @param rsh The handler used to create the result object from
- * the <code>ResultSet</code> of auto-generated keys.
- * @return An object generated by the handler.
- * @throws SQLException if a database access error occurs
- * @since 1.6
+ *
+ * @return An {@link org.apache.commons.dbutils.InsertExecutor} for this SQL statement.
+ * @throws SQLException If there are database or parameter errors.
*/
- public <T> T insert(Connection conn, String sql, ResultSetHandler<T> rsh) throws SQLException {
- return insert(conn, false, sql, rsh, (Object[]) null);
+ public InsertExecutor insert(String sql) throws SQLException {
+ return insert(this.prepareConnection(), true, sql);
}
/**
- * Execute an SQL INSERT query.
- * @param <T> The type of object that the handler returns
- * @param conn The connection to use to run the query.
- * @param sql The SQL to execute.
- * @param rsh The handler used to create the result object from
- * the <code>ResultSet</code> of auto-generated keys.
- * @param params The query replacement parameters.
- * @return An object generated by the handler.
- * @throws SQLException if a database access error occurs
- * @since 1.6
+ * Creates an {@link org.apache.commons.dbutils.InsertExecutor} for the given SQL and connection
+ * The connection is <b>NOT</b> closed after execution.
+ * @param conn The connection to use for the query call.
+ * @param sql The SQL statement to execute.
+ *
+ * @return An {@link org.apache.commons.dbutils.InsertExecutor} for this SQL statement.
+ * @throws SQLException If there are database or parameter errors.
*/
- public <T> T insert(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException {
- return insert(conn, false, sql, rsh, params);
+ public InsertExecutor insert(Connection conn, String sql) throws SQLException {
+ return insert(conn, false, sql);
}
/**
- * Executes the given INSERT SQL statement.
+ * Creates an {@link org.apache.commons.dbutils.InsertExecutor} for the given SQL and connection.
* @param conn The connection to use for the query call.
* @param closeConn True if the connection should be closed, false otherwise.
* @param sql The SQL statement to execute.
- * @param rsh The handler used to create the result object from
- * the <code>ResultSet</code> of auto-generated keys.
- * @param params The query replacement parameters.
- * @return An object generated by the handler.
+ *
+ * @return An {@link org.apache.commons.dbutils.InsertExecutor} for this SQL statement.
* @throws SQLException If there are database or parameter errors.
- * @since 1.6
*/
- private <T> T insert(Connection conn, boolean closeConn, String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException {
+ public InsertExecutor insert(Connection conn, boolean closeConn, String sql) throws SQLException {
if (conn == null) {
throw new SQLException("Null connection");
}
@@ -510,32 +287,7 @@ public class QueryRunner extends Abstrac
}
throw new SQLException("Null SQL statement");
}
-
- if (rsh == null) {
- if (closeConn) {
- close(conn);
- }
- throw new SQLException("Null ResultSetHandler");
- }
-
- PreparedStatement stmt = null;
- T generatedKeys = null;
-
- try {
- stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
- this.fillStatement(stmt, params);
- stmt.executeUpdate();
- ResultSet resultSet = stmt.getGeneratedKeys();
- generatedKeys = rsh.handle(resultSet);
- } catch (SQLException e) {
- this.rethrow(e, sql, params);
- } finally {
- close(stmt);
- if (closeConn) {
- close(conn);
- }
- }
-
- return generatedKeys;
+
+ return new InsertExecutor(conn, sql, closeConn);
}
}
Added: commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/UpdateExecutor.java
URL: http://svn.apache.org/viewvc/commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/UpdateExecutor.java?rev=1450009&view=auto
==============================================================================
--- commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/UpdateExecutor.java (added)
+++ commons/proper/dbutils/branches/2_0/src/main/java/org/apache/commons/dbutils/UpdateExecutor.java Tue Feb 26 03:52:37 2013
@@ -0,0 +1,41 @@
+package org.apache.commons.dbutils;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+
+public class UpdateExecutor extends AbstractExecutor<UpdateExecutor> {
+
+ private final boolean closeConn;
+
+ public UpdateExecutor(final Connection conn, final String sql, final boolean closeConnection) throws SQLException {
+ super(conn, sql);
+ this.closeConn = closeConnection;
+ }
+
+ /**
+ * Calls update after checking the parameters to ensure nothing is null.
+ * @return The number of rows updated.
+ * @throws SQLException If there are database or parameter errors.
+ */
+ public int update() throws SQLException {
+ // throw an exception if there are unmapped parameters
+ this.throwIfUnmappedParams();
+
+ try {
+ return getStatement().executeUpdate();
+ } catch (SQLException e) {
+ this.rethrow(e);
+
+ } finally {
+ close(getStatement());
+ if (closeConn) {
+ close(getConnection());
+ }
+ }
+
+ // we get here only if something is thrown
+ return 0;
+ }
+
+}
Added: commons/proper/dbutils/branches/2_0/src/test/java/org/apache/commons/dbutils/AbstractExecutorTest.java
URL: http://svn.apache.org/viewvc/commons/proper/dbutils/branches/2_0/src/test/java/org/apache/commons/dbutils/AbstractExecutorTest.java?rev=1450009&view=auto
==============================================================================
--- commons/proper/dbutils/branches/2_0/src/test/java/org/apache/commons/dbutils/AbstractExecutorTest.java (added)
+++ commons/proper/dbutils/branches/2_0/src/test/java/org/apache/commons/dbutils/AbstractExecutorTest.java Tue Feb 26 03:52:37 2013
@@ -0,0 +1,108 @@
+/*
+ * 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 org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+
+public class AbstractExecutorTest {
+
+ @SuppressWarnings("rawtypes") // don't care about this in the unit test
+ private AbstractExecutor executor;
+
+ @Mock private Connection conn;
+ @Mock private PreparedStatement stmt;
+
+ @Before
+ public void setup() throws SQLException {
+ MockitoAnnotations.initMocks(this);
+
+ when(conn.prepareStatement(any(String.class))).thenReturn(stmt);
+ }
+
+ @SuppressWarnings("rawtypes")
+ public void createExecutor(String sql) throws SQLException {
+ executor = new AbstractExecutor(conn, sql) { };
+ }
+
+ @Test
+ public void testGoodSql() throws SQLException {
+ createExecutor("select * from blah :first = first and :last=last and phone=:phone");
+
+ verify(conn, times(1)).prepareStatement("select * from blah ? = first and ?=last and phone=?");
+
+ executor.bind("first", "first_name")
+ .bind(":last", "last_name")
+ .bind("phone", Integer.valueOf(12345));
+
+ verify(stmt, times(1)).setObject(1, "first_name");
+ verify(stmt, times(1)).setObject(2, "last_name");
+ verify(stmt, times(1)).setObject(eq(3), eq(Integer.valueOf(12345)));
+
+ executor.throwIfUnmappedParams();
+ }
+
+ @Test
+ public void testNoParamsSql() throws SQLException {
+ createExecutor("select * from blah");
+
+ verify(conn, times(1)).prepareStatement("select * from blah");
+ verify(stmt, times(0)).setObject(any(Integer.class), any(Object.class));
+
+ executor.throwIfUnmappedParams();
+ }
+
+ @Test(expected=SQLException.class)
+ public void testMissingParamSql() throws SQLException {
+ createExecutor("select * from blah :first = first and :last=last");
+
+ verify(conn, times(1)).prepareStatement("select * from blah ? = first and ?=last");
+
+ executor.bind("first", "first_name")
+ .bind(":last", "last_name")
+ .bind("phone", Integer.valueOf(12345)); // should throw
+
+ verify(stmt, times(1)).setObject(1, "first_name");
+ verify(stmt, times(1)).setObject(2, "last_name");
+ verify(stmt, times(1)).setObject(eq(3), eq(Integer.valueOf(12345)));
+ }
+
+ @Test(expected=SQLException.class)
+ public void testDoubleBind() throws SQLException {
+ createExecutor("select * from blah :first = first and :last=last");
+
+ verify(conn, times(1)).prepareStatement("select * from blah ? = first and ?=last");
+
+ executor.bind("first", "first_name")
+ .bind(":last", "last_name")
+ .bind(":last", "last_name");
+
+ verify(stmt, times(1)).setObject(1, "first_name");
+ verify(stmt, times(1)).setObject(2, "last_name");
+ }
+}
Modified: commons/proper/dbutils/branches/2_0/src/test/java/org/apache/commons/dbutils/AsyncQueryRunnerTest.java
URL: http://svn.apache.org/viewvc/commons/proper/dbutils/branches/2_0/src/test/java/org/apache/commons/dbutils/AsyncQueryRunnerTest.java?rev=1450009&r1=1450008&r2=1450009&view=diff
==============================================================================
--- commons/proper/dbutils/branches/2_0/src/test/java/org/apache/commons/dbutils/AsyncQueryRunnerTest.java (original)
+++ commons/proper/dbutils/branches/2_0/src/test/java/org/apache/commons/dbutils/AsyncQueryRunnerTest.java Tue Feb 26 03:52:37 2013
@@ -16,18 +16,12 @@
*/
package org.apache.commons.dbutils;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import java.sql.Connection;
import java.sql.SQLException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import org.apache.commons.dbutils.handlers.ArrayHandler;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
@@ -36,226 +30,64 @@ import org.mockito.MockitoAnnotations;
@SuppressWarnings("boxing") // test code
public class AsyncQueryRunnerTest {
AsyncQueryRunner runner;
- ArrayHandler handler;
@Mock QueryRunner qRunner;
- @Mock Connection conn;
-
+ @Mock ResultSetHandler<Object> handler;
+ @Mock QueryExecutor queryExecutor;
+ @Mock UpdateExecutor updateExecutor;
+ @Mock InsertExecutor insertExecutor;
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this); // init the mocks
- handler = new ArrayHandler();
- runner = new AsyncQueryRunner(Executors.newFixedThreadPool(1), qRunner);
- }
-
- //
- // Batch test cases
- //
- private void callGoodBatch(Connection conn, Object[][] params) throws Exception {
- Future<int[]> future = runner.batch(conn, "select * from blah where ? = ?", params);
-
- future.get();
-
- verify(qRunner, times(1)).batch(eq(conn), any(String.class), eq(params));
- }
-
- private void callGoodBatch(Object[][] params) throws Exception {
- Future<int[]> future = runner.batch("select * from blah where ? = ?", params);
-
- future.get();
-
- verify(qRunner, times(1)).batch(any(String.class), eq(params));
- }
-
- @Test
- public void testGoodBatch() throws Exception {
- String[][] params = new String[][] { { "unit", "unit" }, { "test", "test" } };
-
- callGoodBatch(params);
- }
-
- @Test
- public void testGoodBatchPmdTrue() throws Exception {
- String[][] params = new String[][] { { "unit", "unit" }, { "test", "test" } };
-
- callGoodBatch(params);
- }
-
- @Test
- public void testGoodBatchDefaultConstructor() throws Exception {
- String[][] params = new String[][] { { "unit", "unit" }, { "test", "test" } };
-
- callGoodBatch(conn, params);
+ runner = new AsyncQueryRunner(Executors.newFixedThreadPool(1));
}
@Test
- public void testNullParamsBatch() throws Exception {
- String[][] params = new String[][] { { null, "unit" }, { "test", null } };
-
- callGoodBatch(params);
- }
-
-
-
- // helper method for calling batch when an exception is expected
- private void callBatchWithException(String sql, Object[][] params) throws Exception {
- Future<int[]> future = null;
- boolean caught = false;
-
- try {
- future = runner.batch(sql, params);
-
- future.get();
-
- verify(qRunner, times(1)).batch(any(String.class), params);
- } catch(Exception e) {
- caught = true;
- }
-
- if(!caught)
- fail("Exception never thrown, but expected");
- }
-
- @Test
- public void testTooFewParamsBatch() throws Exception {
- String[][] params = new String[][] { { "unit" }, { "test" } };
-
- callBatchWithException("select * from blah where ? = ?", params);
- }
-
- @Test
- public void testTooManyParamsBatch() throws Exception {
- String[][] params = new String[][] { { "unit", "unit", "unit" }, { "test", "test", "test" } };
-
- callBatchWithException("select * from blah where ? = ?", params);
+ public void testQueryExecutor() throws Exception {
+ runner.query(queryExecutor, handler).get();
+
+ verify(queryExecutor, times(1)).query(handler);
}
@Test(expected=ExecutionException.class)
- public void testExceptionBatch() throws Exception {
- doThrow(ExecutionException.class).when(qRunner).batch(any(String.class), any(Object[][].class));
- runner.batch("select * from blah where ? = ?", null).get();
- }
-
- @Test
- public void testBatchException() throws Exception {
- String[][] params = new String[][] { { "unit", "unit" }, { "test", "test" } };
-
- doThrow(new SQLException()).when(qRunner).batch(any(String.class), any(Object[][].class));
-
- callBatchWithException("select * from blah where ? = ?", params);
- }
-
-
- //
- // Query test cases
- //
- private void callGoodQuery(Connection conn) throws Exception {
- runner.query(conn, "select * from blah where ? = ?", handler, "unit", "test").get();
+ public void testQueryExecutorException() throws Exception {
+ doThrow(SQLException.class).when(queryExecutor).query(handler);
+ runner.query(queryExecutor, handler).get();
- verify(qRunner, times(1)).query(eq(conn), any(String.class), eq(handler), any(String.class), any(String.class));
-
- // call the other variation of query
- runner.query(conn, "select * from blah", handler).get();
-
- verify(qRunner, times(1)).query(eq(conn), any(String.class), eq(handler));
- }
-
- private void callGoodQuery() throws Exception {
- runner.query("select * from blah where ? = ?", handler, "unit", "test").get();
-
- verify(qRunner, times(1)).query(any(String.class), eq(handler), any(String.class), any(String.class));
-
- // call the other variation of query
- runner.query("select * from blah", handler).get();
-
- verify(qRunner, times(1)).query(any(String.class), eq(handler));
+ verify(queryExecutor, times(1)).query(handler);
}
@Test
- public void testGoodQuery() throws Exception {
- callGoodQuery();
- }
-
- @Test
- public void testGoodQueryWithConn() throws Exception {
- callGoodQuery(conn);
+ public void testUpdateExecutor() throws Exception {
+ runner.update(updateExecutor).get();
+
+ verify(updateExecutor, times(1)).update();
}
@Test(expected=ExecutionException.class)
- public void testExecuteQueryException() throws Exception {
- doThrow(new SQLException()).when(qRunner).query(any(String.class), eq(handler), any(String.class), any(String.class));
-
- runner.query("select * from blah where ? = ?", handler, "unit", "test").get();
- }
-
-
- //
- // Update test cases
- //
- private void callGoodUpdate(Connection conn) throws Exception {
- runner.update(conn, "update blah set ? = ?", "unit", "test").get();
-
- verify(qRunner, times(1)).update(eq(conn), any(String.class), any(String.class), any(String.class));
-
- // call the other variation
- runner.update(conn, "update blah set unit = test").get();
-
- verify(qRunner, times(1)).update(eq(conn), any(String.class));
-
- // call the other variation
- runner.update(conn, "update blah set unit = ?", "test").get();
-
- verify(qRunner, times(1)).update(eq(conn), any(String.class), any(String.class));
- }
-
- private void callGoodUpdate() throws Exception {
- runner.update("update blah set ? = ?", "unit", "test").get();
-
- verify(qRunner, times(1)).update(any(String.class), any(String.class), any(String.class));
-
- // call the other variation
- runner.update("update blah set unit = test").get();
-
- verify(qRunner, times(1)).update(any(String.class));
-
- // call the other variation
- runner.update("update blah set unit = ?", "test").get();
-
- verify(qRunner, times(1)).update(any(String.class), any(String.class));
- }
-
- @Test
- public void testGoodUpdate() throws Exception {
- callGoodUpdate();
- }
-
- @Test
- public void testGoodUpdateConnection() throws Exception {
- callGoodUpdate(conn);
+ public void testUpdateExecutorException() throws Exception {
+ doThrow(SQLException.class).when(updateExecutor).update();
+ runner.update(updateExecutor).get();
+
+ verify(updateExecutor, times(1)).update();
}
-
@Test
- public void testInsertUsesGivenQueryRunner() throws Exception {
- runner.insert("1", handler);
- runner.insert("2", handler, "param1");
- runner.insert(conn, "3", handler);
- runner.insert(conn, "4", handler, "param1");
-
- verify(qRunner).insert("1", handler);
- verify(qRunner).insert("2", handler, "param1");
- verify(qRunner).insert(conn, "3", handler);
- verify(qRunner).insert(conn, "4", handler, "param1");
+ public void testInsertExecutor() throws Exception {
+ runner.insert(insertExecutor, handler).get();
+
+ verify(insertExecutor, times(1)).insert(handler);
}
@Test(expected=ExecutionException.class)
- public void testExceptionUpdate() throws Exception {
- doThrow(new SQLException()).when(qRunner).update(any(String.class), any(String.class), any(String.class));
+ public void testInsertExecutorException() throws Exception {
+ doThrow(SQLException.class).when(insertExecutor).insert(handler);
+ runner.insert(insertExecutor, handler).get();
- runner.update("select * from blah where ? = ?", "unit", "test").get();
-
- verify(qRunner, times(1)).update(any(String.class), any(String.class), any(String.class));
+ verify(insertExecutor, times(1)).insert(handler);
}
+
}