class template proc:
public abstract class BatchPreparedStatementSetterWithKeyHolder<T> implements BatchPreparedStatementSetter { private final List<T> beans; public BatchPreparedStatementSetterWithKeyHolder(List<T> beans) { this.beans = beans; } @Override public void setValues(PreparedStatement ps, int i) throws SQLException { setValues(ps, beans.get(i)); } @Override public final int getBatchSize() { return beans.size(); } public void setPrimaryKey(KeyHolder keyHolder) { List<Map<String, Object>> keys = keyHolder.getKeyList(); for (int i = 0, len = keys.size(); i < len; i++) { setPrimaryKey(keys.get(i), beans.get(i)); } } protected abstract void setValues(PreparedStatement ps, T bean) throws SQLException; protected abstract void setPrimaryKey(Map<String, Object> primaryKey, T bean); }
batchupdate utility method:
private static void generatedKeys(PreparedStatement ps, KeyHolder keyHolder) throws SQLException { List<Map<String, Object>> keys = keyHolder.getKeyList(); ResultSet rs = ps.getGeneratedKeys(); if (rs == null) return; try { keys.addAll(new RowMapperResultSetExtractor<Map<String, Object>>(new ColumnMapRowMapper(), 1).extractData(rs)); } finally { UtilIO.close(rs); } } public static <T> int[] batchUpdateWithKeyHolder(JdbcTemplate jdbcTemplate, final String sql, final BatchPreparedStatementSetterWithKeyHolder<T> pss) { return jdbcTemplate.execute(new PreparedStatementCreator() { @Override public PreparedStatement createPreparedStatement(Connection con) throws SQLException { return con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); } }, new PreparedStatementCallback<int[]>() { @Override public int[] doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException { try { int batchSize = pss.getBatchSize(); InterruptibleBatchPreparedStatementSetter ipss = (pss instanceof InterruptibleBatchPreparedStatementSetter ? (InterruptibleBatchPreparedStatementSetter) pss : null); int[] result; KeyHolder keyHolder = new GeneratedKeyHolder(); try { if (JdbcUtils.supportsBatchUpdates(ps.getConnection())) { for (int i = 0; i < batchSize; i++) { pss.setValues(ps, i); if (ipss != null && ipss.isBatchExhausted(i)) break; ps.addBatch(); } result = ps.executeBatch(); generatedKeys(ps, keyHolder); } else { List<Integer> rowsAffected = new ArrayList<Integer>(); for (int i = 0; i < batchSize; i++) { pss.setValues(ps, i); if (ipss != null && ipss.isBatchExhausted(i)) break; rowsAffected.add(ps.executeUpdate()); generatedKeys(ps, keyHolder); } result = UtilObj.tointArray(rowsAffected); } } finally { pss.setPrimaryKey(keyHolder); } return result; } finally { if (pss instanceof ParameterDisposer) ((ParameterDisposer) pss).cleanupParameters(); } } }); }
ex:
UtilJdbc.batchUpdateWithKeyHolder(jdbcTemplate, "insert into tbe_vm_node (creator_id, host, ssh_ip, ssh_user, ssh_passwd)" + " values (?, ?, ?, ?, ?)", new BatchPreparedStatementSetterWithKeyHolder<VmNode>(vmNodes) { @Override protected void setValues(PreparedStatement ps, VmNode vmNode) throws SQLException { UtilJdbc.setValues(ps, vmNode.getCreatorId(), vmNode.getHost(), vmNode.getSshIp(), vmNode.getSshUser(), vmNode.getSshPasswd()); } @Override protected void setPrimaryKey(Map<String, Object> primaryKey, VmNode vmNode) { vmNode.setId((Long) primaryKey.get("abc")); } });