private void insertBatches() throws DaoException, SQLException, InterruptedException { boolean finished = false; Connection cnx = ds.getConnection(); if (isPostGisLoader) { try { ((org.postgresql.PGConnection) cnx) .addDataType("geometry", Class.forName("org.postgis.PGgeometry")); // ((org.postgresql.PGConnection) cnx).addDataType("geometry", // Class.forName("org.postgis.Multipolygon")); } catch (ClassNotFoundException e) { throw new DaoException( "Could not find PostGIS geometry type. Is the PostGIS library in the class path?: " + e.getMessage()); } } PreparedStatement statement = null; try { String[] names = new String[fields.length]; String[] questions = new String[fields.length]; for (int i = 0; i < fields.length; i++) { names[i] = fields[i]; questions[i] = "?"; } String sql = "INSERT INTO " + table + "(" + StringUtils.join(names, ",") + ") " + "VALUES (" + StringUtils.join(questions, ",") + ");"; statement = cnx.prepareStatement(sql); while (!finished && inserterState != InserterState.FAILED) { // accumulate batch int batchSize = 0; while (!finished && batchSize < BATCH_SIZE && inserterState != InserterState.FAILED) { Object row[] = rowBuffer.poll(100, TimeUnit.MILLISECONDS); if (row == null) { // do nothing } else if (row[0] == POSION_PILL) { rowBuffer.put(new Object[] {POSION_PILL}); finished = true; } else { batchSize++; for (int i = 0; i < row.length; i++) { if (row[i] != null && row[i].getClass().equals(java.lang.Character.class)) statement.setObject(i + 1, row[i].toString()); else statement.setObject(i + 1, row[i]); } statement.addBatch(); } } try { statement.executeBatch(); cnx.commit(); } catch (SQLException e) { cnx.rollback(); while (e != null) { LOG.error("insert batch failed, attempting to continue:", e); e = e.getNextException(); } } statement.clearBatch(); } } finally { if (statement != null) { JDBCUtils.safeClose(statement); } AbstractSqlDao.quietlyCloseConn(cnx); } }
@Override protected final int execute(ExecuteContext ctx, ExecuteListener listener) throws SQLException { if (returning.isEmpty()) { return super.execute(ctx, listener); } else { int result = 1; ResultSet rs; switch (ctx.configuration().dialect()) { // SQLite can select _rowid_ after the insert case SQLITE: { listener.executeStart(ctx); result = ctx.statement().executeUpdate(); listener.executeEnd(ctx); DSLContext create = DSL.using(ctx.connection(), SQLDialect.SQLITE, ctx.configuration().settings()); returned = create .select(returning) .from(getInto()) .where(rowid().equal(rowid().getDataType().convert(create.lastID()))) .fetchInto(getInto()); return result; } // Sybase can select @@identity after the insert // TODO [#832] Fix this. This might be a driver issue. JDBC // Generated keys don't work with jconn3, but they seem to work // with jTDS (which is used for Sybase ASE integration) case CUBRID: case SYBASE: { listener.executeStart(ctx); result = ctx.statement().executeUpdate(); listener.executeEnd(ctx); selectReturning(ctx.configuration(), create(ctx.configuration()).lastID()); return result; } // Some dialects can only retrieve "identity" (AUTO_INCREMENT) values // Additional values have to be fetched explicitly // [#1260] TODO CUBRID supports this, but there's a JDBC bug case ASE: case DERBY: case H2: case INGRES: case MYSQL: case SQLSERVER: { listener.executeStart(ctx); result = ctx.statement().executeUpdate(); listener.executeEnd(ctx); rs = ctx.statement().getGeneratedKeys(); try { List<Object> list = new ArrayList<Object>(); // Some JDBC drivers seem to illegally return null // from getGeneratedKeys() sometimes if (rs != null) { while (rs.next()) { list.add(rs.getObject(1)); } } selectReturning(ctx.configuration(), list.toArray()); return result; } finally { JDBCUtils.safeClose(rs); } } // Firebird and Postgres can execute the INSERT .. RETURNING // clause like a select clause. JDBC support is not implemented // in the Postgres JDBC driver case FIREBIRD: case POSTGRES: { listener.executeStart(ctx); rs = ctx.statement().executeQuery(); listener.executeEnd(ctx); break; } // These dialects have full JDBC support case DB2: case HSQLDB: case ORACLE: default: { listener.executeStart(ctx); result = ctx.statement().executeUpdate(); listener.executeEnd(ctx); rs = ctx.statement().getGeneratedKeys(); break; } } ExecuteContext ctx2 = new DefaultExecuteContext(ctx.configuration()); ExecuteListener listener2 = new ExecuteListeners(ctx2); ctx2.resultSet(rs); returned = new CursorImpl<R>(ctx2, listener2, fieldArray(returning), null, true, false) .fetch() .into(getInto()); return result; } }
@Override public final void close() { JDBCUtils.safeClose(rs); rs = null; isClosed = true; }