class DBQueries {

    public static <K,A> int bulkAdd(Iterable<Row<K, A>> rows, final String tableName, final Connection connection){
        final String sql = String.format("INSERT OR IGNORE INTO cqtbl_%s values(?, ?);", tableName);
        PreparedStatement statement = null;
        int totalRowsModified = 0;
        try {
            statement = connection.prepareStatement(sql);

            for (Row<K, A> row : rows) {
                statement.setObject(1, row.getObjectKey());
                statement.setObject(2, row.getValue());
                statement.addBatch();
            }
            int[] rowsModified = statement.executeBatch();
            for (int m : rowsModified) {
                ensureNotNegative(m);
                totalRowsModified += m;
            }
            return totalRowsModified;
        }
        catch (NullPointerException e) {
            // Note: here we catch a and rethrow NullPointerException,
            // to allow compatibility with Java Collections Framework,
            // which requires NPE to be thrown for null arguments...
            boolean rolledBack = DBUtils.rollback(connection);
            NullPointerException npe = new NullPointerException("Unable to bulk add rows containing a null object to the index table: "+ tableName + ". Rolled back: " + rolledBack);
            npe.initCause(e);
            throw npe;
        }
        catch (Exception e){
            boolean rolledBack = DBUtils.rollback(connection);
            throw new IllegalStateException("Unable to bulk add rows to the index table: "+ tableName + ". Rolled back: " + rolledBack, e);
        }finally {
            DBUtils.closeQuietly(statement);
        }
    }

}