From 87753db18ab8d9a646f366f49f021b9f779c3386 Mon Sep 17 00:00:00 2001 From: mdb Date: Thu, 8 Jun 2006 21:32:58 +0000 Subject: [PATCH] Added batchQuery(). git-svn-id: https://samskivert.googlecode.com/svn/trunk@1852 6335cc39-0255-0410-8fd6-9bcaacd3b74c --- src/java/com/samskivert/jdbc/JDBCUtil.java | 70 ++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/src/java/com/samskivert/jdbc/JDBCUtil.java b/src/java/com/samskivert/jdbc/JDBCUtil.java index 021cff28..318437f8 100644 --- a/src/java/com/samskivert/jdbc/JDBCUtil.java +++ b/src/java/com/samskivert/jdbc/JDBCUtil.java @@ -22,6 +22,8 @@ package com.samskivert.jdbc; import java.io.InputStream; import java.io.UnsupportedEncodingException; +import java.util.Collection; +import java.util.Iterator; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -39,6 +41,17 @@ import com.samskivert.util.StringUtil; */ public class JDBCUtil { + /** Used for {@link #batchQuery}. */ + public interface BatchProcessor + { + /** + * Called for each row returned during our batch query. Do not advance + * the result set, simply query its values with the get methods. + */ + public void process (ResultSet row) + throws SQLException; + }; + /** * Closes the supplied JDBC statement and gracefully handles being * passed null (by doing nothing). @@ -117,6 +130,63 @@ public class JDBCUtil } } + /** + * Issues a query with a potentially large number of keys in batches. + * For example, you might have 10,000 ids that you wish to use in an "in" + * clause, but don't trust the database to be smart about optimizing that + * many keys, so instead you use batchQuery like so: + *
+     *    Collection keys = ...;
+     *    String query = "select NAME from USERS where USER_ID in (#KEYS)";
+     *    JDBCUtil.BatchProcessor proc = new JDBCUtil.BatchProcessor() {
+     *        public void process (ResultSet row) {
+     *            String name = rs.getString(1);
+     *            // do whatever with name
+     *        }
+     *    };
+     *    JDBCUtil.batchQuery(conn, query, keys, false, 500, proc);
+     * 
+ * + * @param query the SQL query to run for each batch with the string + * #KEYS# in the place where the batch of keys should be + * substituted. + * @param escapeKeys if true, {@link #escape} will be called on each key to + * escape any dangerous characters and wrap the key in quotes. + * @param batchSize the number of keys at a time to substitute in for + * #KEYS#. + */ + public static void batchQuery ( + Connection conn, String query, Collection keys, + boolean escapeKeys, int batchSize, BatchProcessor processor) + throws SQLException + { + Statement stmt = conn.createStatement(); + try { + Iterator itr = keys.iterator(); + while (itr.hasNext()) { + // group one batch of keys together + StringBuilder buf = new StringBuilder(); + for (int ii = 0; ii < batchSize && itr.hasNext(); ii++) { + if (ii > 0) { + buf.append(","); + } + String key = String.valueOf(itr.next()); + buf.append(escapeKeys ? escape(key) : key); + } + + // issue the query with that batch + String squery = query.replace("#KEYS#", buf.toString()); + ResultSet rs = stmt.executeQuery(squery); + while (rs.next()) { + processor.process(rs); + } + } + + } finally { + close(stmt); + } + } + /** * Calls stmt.executeUpdate() on the supplied statement * with the supplied query, checking to see that it returns the