package com.github.ltsopensource.store.jdbc.dbutils; import java.sql.*; import java.util.Arrays; /** * from dbutils */ public class DbRunner { private volatile boolean pmdKnownBroken = false; public int[] batch(Connection conn, String sql, Object[][] params) throws SQLException { return this.batch(conn, false, sql, params); } private int[] batch(Connection conn, boolean closeConn, String sql, Object[][] params) throws SQLException { if (conn == null) { throw new SQLException("Null connection"); } if (sql == null) { if (closeConn) { close(conn); } throw new SQLException("Null SQL statement"); } if (params == null) { if (closeConn) { close(conn); } throw new SQLException("Null parameters. If parameters aren't need, pass an empty array."); } PreparedStatement stmt = null; int[] rows = null; try { stmt = conn.prepareStatement(sql); for (Object[] param : params) { this.fillStatement(stmt, param); stmt.addBatch(); } rows = stmt.executeBatch(); } catch (SQLException e) { this.rethrow(e, sql, (Object[]) params); } finally { close(stmt); if (closeConn) { close(conn); } } return rows; } public int update(Connection conn, String sql, Object... params) throws SQLException { return update(conn, false, sql, params); } private int update(Connection conn, boolean closeConn, String sql, Object... params) throws SQLException { if (conn == null) { throw new SQLException("Null connection"); } if (sql == null) { if (closeConn) { close(conn); } throw new SQLException("Null SQL statement"); } PreparedStatement stmt = null; int rows = 0; try { stmt = conn.prepareStatement(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; } public <T> T query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException { return this.<T>query(conn, false, sql, rsh, params); } private <T> T query(Connection conn, boolean closeConn, String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException { if (conn == null) { throw new SQLException("Null connection"); } if (sql == null) { if (closeConn) { close(conn); } 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 = conn.prepareStatement(sql); this.fillStatement(stmt, params); rs = 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; } private void close(Connection conn) throws SQLException { if (conn != null) { conn.close(); } } private void close(Statement stmt) throws SQLException { if (stmt != null) { stmt.close(); } } private void close(ResultSet rs) throws SQLException { if (rs != null) { rs.close(); } } 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. */ assert pmd != null; sqlType = pmd.getParameterType(i + 1); } catch (SQLException e) { pmdKnownBroken = true; } } stmt.setNull(i + 1, sqlType); } } } private void rethrow(SQLException cause, String sql, Object... params) throws SQLException { String causeMessage = cause.getMessage(); if (causeMessage == null) { causeMessage = ""; } StringBuilder msg = new StringBuilder(causeMessage); msg.append(" Query: "); msg.append(sql); msg.append(" Parameters: "); if (params == null) { msg.append("[]"); } else { msg.append(Arrays.deepToString(params)); } SQLException e = new SQLException(msg.toString(), cause.getSQLState(), cause.getErrorCode()); e.setNextException(cause); throw e; } }