I've written a class to dynamically generate such a multi-parameter query. It currently has some limitations (for quickness of writing) and has not been thoroughly tested, but may be a good way to get you started. Limitations:
- Only handles one multi-argument parameter (??)
- Falsely recognizes question marks in quotes as parameters
- API is not pretty but the alternative was writing a full-on PreparedStatement decorator with lots of state management and that was more work than I was willing to put into it.
Source:
/**
 * A PreparedStatement decorator that can bind a set of arguments
 *
 * A specialized ?? placeholder in a string can be bound to a set of
 * values instead of just single values. Currently, only one such
 * specialized placeholder is supported, and you must bind it before
 * obtaining the prepared statement.
 *
 * If you want to bind additional values to the PreparedStatement after
 * producing it, you must run the parameter index through the param()
 * method.
 *
 * Example use:
 *
 * 
 *     MultiValueBinder binder = new MultiValueBinder(
 *          "UPDATE table SET value = ? WHERE id IN (??)", conn);
 *     binder.setInts(myIds);
 *
 *     PreparedStatement stmt = binder.statement();
 *     stmt.setString(binder.param(1), "myValue");
 *
 *     ResultSet rs = stmt.executeQuery();
 *
 * Note: this class is not robust against using question marks in literal
 * strings. Don't use them :).
 */
public class MultiValueBinder {
    private Connection connection;
    private PreparedStatement statement;
    private String sql;
    private int argumentsBefore = 0;
    private int setSize         = 0;
    public MultiValueBinder(String sql, Connection connection) {
        this.sql        = sql;
        this.connection = connection;
    }
    /**
     * Bind a collection of integers to the multi-valued argument
     */
    public void setInts(Collection<Integer> ints) throws SQLException {
        explodeQuery(ints.size());
        buildStatement();
        try {
            int i = 0;
            for (Integer integer: ints)
                statement.setInt(1 + argumentsBefore + i++, integer);
        } catch (Exception ex) {
            cleanStatement();
            throw (ex instanceof SQLException) ? (SQLException) ex : new SQLException(ex);
        }
    }
    /**
     * Bind a collection of strings to the multi-valued argument
     */
    public void setStrings(Collection<String> strings) throws SQLException {
        explodeQuery(strings.size());
        buildStatement();
        try {
            int i = 0;
            for (String str: strings)
                statement.setString(1 + argumentsBefore + i++, str);
        } catch (Exception ex) {
            cleanStatement();
            throw (ex instanceof SQLException) ? (SQLException) ex : new SQLException(ex);
        }
    }
    /**
     * Explode the multi-value parameter into a sequence of comma-separated
     * question marks.
     */
    private void explodeQuery(int size) throws SQLException {
        int mix = sql.indexOf("??");
        if (mix == -1) throw new SQLException("Query does not contain a multi-valued argument.");
        if (size == 0) throw new SQLException("Can't bind an empty collection; generated SQL won't parse.");
        // Count the number of arguments before the multi-marker
        argumentsBefore = 0;
        for (int i = 0; i < mix; i++) {
            if (sql.charAt(i) == '?') argumentsBefore++;
        }
        setSize = size;
        // Generate the exploded SQL query
        StringBuilder sb = new StringBuilder(sql.substring(0, mix)); // Start
        for (int i = 0; i < setSize; i++) {                          // ?, ?, ...
            if (i > 0) sb.append(", ");
            sb.append('?');
        }
        sb.append(sql.substring(mix + 2));                           // Remainder
        sql = sb.toString();
    }
    /**
     * Create the statement if it hasn't been created yet
     */
    private void buildStatement() throws SQLException {
        if (statement != null) return;
        if (sql.contains("??"))
            throw new SQLException("Multi-valued argument not bound yet.");
        statement = connection.prepareStatement(sql);
    }
    private void cleanStatement() {
        if (statement != null) {
            try {
                statement.close();
            } catch (Exception ex) {
                /* Ignore */
            }
            statement = null;
        }
    }
    public PreparedStatement statement() throws SQLException {
        buildStatement();
        return statement;
    }
    /**
     * Transform the 1-based-index of the given argument before query expansion
     * into the index after expansion.
     *
     * The ?? placeholder takes up one index slot.
     */
    public int param(int ix) {
        if (ix <= argumentsBefore) return ix;
        if (ix == argumentsBefore + 1)
            throw new RuntimeException(ix + " is the index of the multi-valued parameter.");
        return argumentsBefore + 1 + setSize;
    }
}