package bjc.utils.misc; import java.math.BigDecimal; import java.sql.Array; import java.sql.Blob; import java.sql.Clob; import java.sql.Date; import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Parent class for {@link NamedPreparedStatement} * * Used mostly for cases where you want to prepare the bindings independently of the actual query. */ public class BoundPreparedStatement { protected final Map singles = new HashMap<>(); protected final Map> lists = new HashMap<>(); protected final List batch = new ArrayList<>(); private static List toBinders(Collection values, int sqlType, boolean forceType) { ArrayList list = new ArrayList<>(values.size()); for (Object v : values) { final Object val = v; if (forceType) { list.add((ps, i) -> { if (val == null) ps.setNull(i, sqlType); else ps.setObject(i, val, sqlType); }); } else { list.add((ps, i) -> ps.setObject(i, val)); } } return list; } /** * Record the current set of parameters as a batch and start a new one. * * @return The prepared statement */ public BoundPreparedStatement addBatch() { batch.add(new ParamSnapshot(new HashMap<>(singles), deepCopyLists(lists))); return this; } /** * Clear the currently bound parameters. * * @return The prepared statement */ public BoundPreparedStatement clearParameters() { singles.clear(); lists.clear(); return this; } /** * Bind a object as a parameter * * @param name The name of the parameter * @param value The value for the parameter * @return The prepared statement */ public BoundPreparedStatement setObject(String name, Object value) { singles.put(name, (ps, i) -> ps.setObject(i, value)); return this; } /** * Bind a object as a parameter * * @param name The name of the parameter * @param value The value for the parameter * @param sqlType The SQL type for the parameter (see {@link java.sql.Types}) * @return The prepared statement */ public BoundPreparedStatement setObject(String name, Object value, int sqlType) { singles.put(name, (ps, i) -> { if (value == null) ps.setNull(i, sqlType); else ps.setObject(i, value, sqlType); }); return this; } /** * Bind a null as a parameter * * @param name The name of the parameter * @param sqlType The SQL type for the parameter (see {@link java.sql.Types}) * @return The prepared statement */ public BoundPreparedStatement setNull(String name, int sqlType) { singles.put(name, (ps, i) -> ps.setNull(i, sqlType)); return this; } /** * Bind a boolean as a parameter * * @param n The name of the parameter * @param x The value for the parameter * @return The prepared statement */ public BoundPreparedStatement setBoolean(String n, boolean x) { singles.put(n, (ps, i) -> ps.setBoolean(i, x)); return this; } /** * Bind a byte as a parameter * * @param n The name of the parameter * @param x The value for the parameter * @return The prepared statement */ public BoundPreparedStatement setByte(String n, byte x) { singles.put(n, (ps, i) -> ps.setByte(i, x)); return this; } /** * Bind a short as a parameter * * @param n The name of the parameter * @param x The value for the parameter * @return The prepared statement */ public BoundPreparedStatement setShort(String n, short x) { singles.put(n, (ps, i) -> ps.setShort(i, x)); return this; } /** * Bind a int as a parameter * * @param n The name of the parameter * @param x The value for the parameter * @return The prepared statement */ public BoundPreparedStatement setInt(String n, int x) { singles.put(n, (ps, i) -> ps.setInt(i, x)); return this; } /** * Bind a long as a parameter * * @param n The name of the parameter * @param x The value for the parameter * @return The prepared statement */ public BoundPreparedStatement setLong(String n, long x) { singles.put(n, (ps, i) -> ps.setLong(i, x)); return this; } /** * Bind a float as a parameter * * @param n The name of the parameter * @param x The value for the parameter * @return The prepared statement */ public BoundPreparedStatement setFloat(String n, float x) { singles.put(n, (ps, i) -> ps.setFloat(i, x)); return this; } /** * Bind a double as a parameter * * @param n The name of the parameter * @param x The value for the parameter * @return The prepared statement */ public BoundPreparedStatement setDouble(String n, double x) { singles.put(n, (ps, i) -> ps.setDouble(i, x)); return this; } /** * Bind a {@link BigDecimal} as a parameter * * @param n The name of the parameter * @param x The value for the parameter * @return The prepared statement */ public BoundPreparedStatement setBigDecimal(String n, BigDecimal x) { singles.put(n, (ps, i) -> ps.setBigDecimal(i, x)); return this; } /** * Bind a string as a parameter * * @param n The name of the parameter * @param x The value for the parameter * @return The prepared statement */ public BoundPreparedStatement setString(String n, String x) { singles.put(n, (ps, i) -> ps.setString(i, x)); return this; } /** * Bind a byte-array as a parameter * * @param n The name of the parameter * @param x The value for the parameter * @return The prepared statement */ public BoundPreparedStatement setBytes(String n, byte[] x) { singles.put(n, (ps, i) -> ps.setBytes(i, x)); return this; } /** * Bind a date as a parameter * * @param n The name of the parameter * @param x The value for the parameter * @return The prepared statement */ public BoundPreparedStatement setDate(String n, Date x) { singles.put(n, (ps, i) -> ps.setDate(i, x)); return this; } /** * Bind a date as a parameter * * @param n The name of the parameter * @param x The value for the parameter * @param c The calendar for the date * @return The prepared statement */ public BoundPreparedStatement setDate(String n, Date x, Calendar c) { singles.put(n, (ps, i) -> ps.setDate(i, x, c)); return this; } /** * Bind a time-value as a parameter * * @param n The name of the parameter * @param x The value for the parameter * @return The prepared statement */ public BoundPreparedStatement setTime(String n, Time x) { singles.put(n, (ps, i) -> ps.setTime(i, x)); return this; } /** * Bind a time-value as a parameter * * @param n The name of the parameter * @param x The value for the parameter * @param c The calendar for the time * @return The prepared statement */ public BoundPreparedStatement setTime(String n, Time x, Calendar c) { singles.put(n, (ps, i) -> ps.setTime(i, x, c)); return this; } /** * Bind a timestamp as a parameter * * @param n The name of the parameter * @param x The value for the parameter * @return The prepared statement */ public BoundPreparedStatement setTimestamp(String n, Timestamp x) { singles.put(n, (ps, i) -> ps.setTimestamp(i, x)); return this; } /** * Bind a timestamp as a parameter * * @param n The name of the parameter * @param x The value for the parameter * @param c The calendar for the timestamp * @return The prepared statement */ public BoundPreparedStatement setTimestamp(String n, Timestamp x, Calendar c) { singles.put(n, (ps, i) -> ps.setTimestamp(i, x, c)); return this; } /** * Bind a {@link Array} as a parameter * * @param n The name of the parameter * @param x The value for the parameter * @return The prepared statement */ public BoundPreparedStatement setArray(String n, Array x) { singles.put(n, (ps, i) -> ps.setArray(i, x)); return this; } /** * Bind a {@link Blob} as a parameter * * @param n The name of the parameter * @param x The value for the parameter * @return The prepared statement */ public BoundPreparedStatement setBlob(String n, Blob x) { singles.put(n, (ps, i) -> ps.setBlob(i, x)); return this; } /** * Bind a {@link Clob} as a parameter * * @param n The name of the parameter * @param x The value for the parameter * @return The prepared statement */ public BoundPreparedStatement setClob(String n, Clob x) { singles.put(n, (ps, i) -> ps.setClob(i, x)); return this; } /** * Bind a URL as a parameter * * @param n The name of the parameter * @param x The value for the parameter * @return The prepared statement */ public BoundPreparedStatement setURL(String n, java.net.URL x) { singles.put(n, (ps, i) -> ps.setURL(i, x)); return this; } /** * Bind a ASCII stream as a parameter * * @param n The name of the parameter * @param x The value for the parameter * @param len The length of the stream * @return The prepared statement */ public BoundPreparedStatement setAsciiStream(String n, java.io.InputStream x, int len) { singles.put(n, (ps, i) -> ps.setAsciiStream(i, x, len)); return this; } /** * Bind a binary stream as a parameter * * @param n The name of the parameter * @param x The value for the parameter * @param len The length of the stream * @return The prepared statement */ public BoundPreparedStatement setBinaryStream(String n, java.io.InputStream x, int len) { singles.put(n, (ps, i) -> ps.setBinaryStream(i, x, len)); return this; } /** * Bind a character stream as a parameter * * @param n The name of the parameter * @param r The value for the parameter * @param len The length of the stream * @return The prepared statement */ public BoundPreparedStatement setCharacterStream(String n, java.io.Reader r, int len) { singles.put(n, (ps, i) -> ps.setCharacterStream(i, r, len)); return this; } /** * Bind a list parameter to the statement * * @param name The name of the list parameter * @param values The values for the list parameter * @return The prepared statement */ public BoundPreparedStatement setList(String name, Collection values) { lists.put(name, toBinders(values, Types.OTHER, false)); return this; } /** * Bind a list parameter to the statement * * @param name The name of the list parameter * @param values The values for the list parameter * @return The prepared statement */ public BoundPreparedStatement setList(String name, Object... values) { lists.put(name, toBinders(Arrays.asList(values), Types.OTHER, false)); return this; } /** * Explicit SQL type for all elements (useful if nulls might appear). * * @param name The name of the list parameter * @param sqlType The SQL type for the parameters * @param values The values for the list parameter * @return The prepared statement */ public BoundPreparedStatement setList(String name, int sqlType, Collection values) { lists.put(name, toBinders(values, sqlType, true)); return this; } /** * Explicit SQL type for all elements (useful if nulls might appear). * * @param name The name of the list parameter * @param sqlType The SQL type for the parameters * @param values The values for the list parameter * @return The prepared statement */ public BoundPreparedStatement setList(String name, int sqlType, Object... values) { lists.put(name, toBinders(Arrays.asList(values), sqlType, true)); return this; } private static Map> deepCopyLists(Map> src) { Map> m = new HashMap<>(src.size()); for (Map.Entry> e : src.entrySet()) { m.put(e.getKey(), new ArrayList<>(e.getValue())); } return m; } /** * Create a new {@link BoundPreparedStatement} */ public BoundPreparedStatement() { } }