|
|
|
@ -996,21 +996,10 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { |
|
|
|
|
|
|
|
|
|
|
|
return updateCount(execute(psc, ps -> { |
|
|
|
return updateCount(execute(psc, ps -> { |
|
|
|
int rows = ps.executeUpdate(); |
|
|
|
int rows = ps.executeUpdate(); |
|
|
|
List<Map<String, Object>> generatedKeys = generatedKeyHolder.getKeyList(); |
|
|
|
generatedKeyHolder.getKeyList().clear(); |
|
|
|
generatedKeys.clear(); |
|
|
|
storeGeneratedKeys(generatedKeyHolder, ps, 1); |
|
|
|
ResultSet keys = ps.getGeneratedKeys(); |
|
|
|
|
|
|
|
if (keys != null) { |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
RowMapperResultSetExtractor<Map<String, Object>> rse = |
|
|
|
|
|
|
|
new RowMapperResultSetExtractor<>(getColumnMapRowMapper(), 1); |
|
|
|
|
|
|
|
generatedKeys.addAll(result(rse.extractData(keys))); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
finally { |
|
|
|
|
|
|
|
JdbcUtils.closeResultSet(keys); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (logger.isTraceEnabled()) { |
|
|
|
if (logger.isTraceEnabled()) { |
|
|
|
logger.trace("SQL update affected " + rows + " rows and returned " + generatedKeys.size() + " keys"); |
|
|
|
logger.trace("SQL update affected " + rows + " rows and returned " + generatedKeyHolder.getKeyList().size() + " keys"); |
|
|
|
} |
|
|
|
} |
|
|
|
return rows; |
|
|
|
return rows; |
|
|
|
}, true)); |
|
|
|
}, true)); |
|
|
|
@ -1031,6 +1020,14 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { |
|
|
|
return update(sql, newArgPreparedStatementSetter(args)); |
|
|
|
return update(sql, newArgPreparedStatementSetter(args)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public int[] batchUpdate(final PreparedStatementCreator psc, final BatchPreparedStatementSetter pss, final KeyHolder generatedKeyHolder) throws DataAccessException { |
|
|
|
|
|
|
|
int[] result = execute(psc, getPreparedStatementCallback(pss, generatedKeyHolder)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Assert.state(result != null, "No result array"); |
|
|
|
|
|
|
|
return result; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public int[] batchUpdate(String sql, final BatchPreparedStatementSetter pss) throws DataAccessException { |
|
|
|
public int[] batchUpdate(String sql, final BatchPreparedStatementSetter pss) throws DataAccessException { |
|
|
|
if (logger.isDebugEnabled()) { |
|
|
|
if (logger.isDebugEnabled()) { |
|
|
|
@ -1041,43 +1038,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { |
|
|
|
return new int[0]; |
|
|
|
return new int[0]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int[] result = execute(sql, (PreparedStatementCallback<int[]>) ps -> { |
|
|
|
int[] result = execute(sql, getPreparedStatementCallback(pss, null)); |
|
|
|
try { |
|
|
|
|
|
|
|
InterruptibleBatchPreparedStatementSetter ipss = |
|
|
|
|
|
|
|
(pss instanceof InterruptibleBatchPreparedStatementSetter ibpss ? ibpss : null); |
|
|
|
|
|
|
|
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(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return ps.executeBatch(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
List<Integer> rowsAffected = new ArrayList<>(); |
|
|
|
|
|
|
|
for (int i = 0; i < batchSize; i++) { |
|
|
|
|
|
|
|
pss.setValues(ps, i); |
|
|
|
|
|
|
|
if (ipss != null && ipss.isBatchExhausted(i)) { |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
rowsAffected.add(ps.executeUpdate()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
int[] rowsAffectedArray = new int[rowsAffected.size()]; |
|
|
|
|
|
|
|
for (int i = 0; i < rowsAffectedArray.length; i++) { |
|
|
|
|
|
|
|
rowsAffectedArray[i] = rowsAffected.get(i); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return rowsAffectedArray; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
finally { |
|
|
|
|
|
|
|
if (pss instanceof ParameterDisposer parameterDisposer) { |
|
|
|
|
|
|
|
parameterDisposer.cleanupParameters(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Assert.state(result != null, "No result array"); |
|
|
|
Assert.state(result != null, "No result array"); |
|
|
|
return result; |
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -1604,6 +1565,71 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { |
|
|
|
return result; |
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void storeGeneratedKeys(KeyHolder generatedKeyHolder, PreparedStatement ps, int rowsExpected) throws SQLException { |
|
|
|
|
|
|
|
List<Map<String, Object>> generatedKeys = generatedKeyHolder.getKeyList(); |
|
|
|
|
|
|
|
ResultSet keys = ps.getGeneratedKeys(); |
|
|
|
|
|
|
|
if (keys != null) { |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
RowMapperResultSetExtractor<Map<String, Object>> rse = |
|
|
|
|
|
|
|
new RowMapperResultSetExtractor<>(getColumnMapRowMapper(), rowsExpected); |
|
|
|
|
|
|
|
generatedKeys.addAll(result(rse.extractData(keys))); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
finally { |
|
|
|
|
|
|
|
JdbcUtils.closeResultSet(keys); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private PreparedStatementCallback<int[]> getPreparedStatementCallback(BatchPreparedStatementSetter pss, @Nullable KeyHolder generatedKeyHolder) { |
|
|
|
|
|
|
|
return ps -> { |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
int batchSize = pss.getBatchSize(); |
|
|
|
|
|
|
|
InterruptibleBatchPreparedStatementSetter ipss = |
|
|
|
|
|
|
|
(pss instanceof InterruptibleBatchPreparedStatementSetter ibpss ? ibpss : null); |
|
|
|
|
|
|
|
if (generatedKeyHolder != null) { |
|
|
|
|
|
|
|
generatedKeyHolder.getKeyList().clear(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
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(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
int[] results = ps.executeBatch(); |
|
|
|
|
|
|
|
if (generatedKeyHolder != null) { |
|
|
|
|
|
|
|
storeGeneratedKeys(generatedKeyHolder, ps, batchSize); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return results; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
List<Integer> rowsAffected = new ArrayList<>(); |
|
|
|
|
|
|
|
for (int i = 0; i < batchSize; i++) { |
|
|
|
|
|
|
|
pss.setValues(ps, i); |
|
|
|
|
|
|
|
if (ipss != null && ipss.isBatchExhausted(i)) { |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
rowsAffected.add(ps.executeUpdate()); |
|
|
|
|
|
|
|
if (generatedKeyHolder != null) { |
|
|
|
|
|
|
|
storeGeneratedKeys(generatedKeyHolder, ps, 1); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
int[] rowsAffectedArray = new int[rowsAffected.size()]; |
|
|
|
|
|
|
|
for (int i = 0; i < rowsAffectedArray.length; i++) { |
|
|
|
|
|
|
|
rowsAffectedArray[i] = rowsAffected.get(i); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return rowsAffectedArray; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
finally { |
|
|
|
|
|
|
|
if (pss instanceof ParameterDisposer parameterDisposer) { |
|
|
|
|
|
|
|
parameterDisposer.cleanupParameters(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Invocation handler that suppresses close calls on JDBC Connections. |
|
|
|
* Invocation handler that suppresses close calls on JDBC Connections. |
|
|
|
|