Skip to content

Commit 21d0a7f

Browse files
committed
Update BatchJdbcOperations to more closely mirror proprosed updates to NamedParameterJdbcOperations in spring-jdbc.
1 parent e79f192 commit 21d0a7f

File tree

1 file changed

+46
-63
lines changed

1 file changed

+46
-63
lines changed

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/BatchJdbcOperations.java

+46-63
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.sql.PreparedStatement;
1919
import java.sql.ResultSet;
2020
import java.sql.SQLException;
21+
import java.util.ArrayList;
2122
import java.util.List;
2223
import java.util.Map;
2324

@@ -29,89 +30,71 @@ public BatchJdbcOperations(JdbcOperations jdbcOperations) {
2930
}
3031

3132
@Nullable
32-
int[] batchUpdate(String insertSql, SqlParameterSource[] sqlParameterSources,
33-
KeyHolder generatedKeyHolder) {
34-
// TODO: This is largely duplicated from spring-jdbc and should be replaced with a call into
35-
// NamedParameterJdbcTemplate#batchUpdate once a method taking KeyHolder is added there.
36-
ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(insertSql);
37-
SqlParameterSource paramSource = sqlParameterSources[0];
33+
int[] batchUpdate(String sql, SqlParameterSource[] batchArgs, KeyHolder generatedKeyHolder) {
34+
return batchUpdate(sql, batchArgs, generatedKeyHolder, null);
35+
}
36+
37+
@Nullable
38+
public int[] batchUpdate(String sql, SqlParameterSource[] batchArgs, KeyHolder generatedKeyHolder,
39+
String[] keyColumnNames) {
40+
if (batchArgs.length == 0) {
41+
return new int[0];
42+
}
43+
44+
ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(sql);
45+
SqlParameterSource paramSource = batchArgs[0];
3846
String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource);
3947
List<SqlParameter> declaredParameters = NamedParameterUtils.buildSqlParameterList(parsedSql, paramSource);
4048
PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(sqlToUse, declaredParameters);
41-
pscf.setReturnGeneratedKeys(true);
49+
if (keyColumnNames != null) {
50+
pscf.setGeneratedKeysColumnNames(keyColumnNames);
51+
} else {
52+
pscf.setReturnGeneratedKeys(true);
53+
}
4254
Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, null);
4355
PreparedStatementCreator psc = pscf.newPreparedStatementCreator(params);
4456
BatchPreparedStatementSetter bpss = new BatchPreparedStatementSetter() {
4557
@Override
4658
public void setValues(PreparedStatement ps, int i) throws SQLException {
47-
Object[] values = NamedParameterUtils.buildValueArray(parsedSql, sqlParameterSources[i], null);
59+
Object[] values = NamedParameterUtils.buildValueArray(parsedSql, batchArgs[i], null);
4860
pscf.newPreparedStatementSetter(values).setValues(ps);
4961
}
5062

5163
@Override
5264
public int getBatchSize() {
53-
return sqlParameterSources.length;
65+
return batchArgs.length;
5466
}
5567
};
5668
PreparedStatementCallback<int[]> preparedStatementCallback = ps -> {
5769
int batchSize = bpss.getBatchSize();
58-
for (int i = 0; i < batchSize; i++) {
59-
bpss.setValues(ps, i);
60-
ps.addBatch();
61-
}
62-
int[] results = ps.executeBatch();
63-
List<Map<String, Object>> generatedKeys = ((KeyHolder) generatedKeyHolder).getKeyList();
64-
generatedKeys.clear();
65-
ResultSet keys = ps.getGeneratedKeys();
66-
if (keys != null) {
67-
try {
68-
RowMapperResultSetExtractor<Map<String, Object>> rse =
69-
new RowMapperResultSetExtractor<>(new ColumnMapRowMapper(), 1);
70-
//noinspection ConstantConditions
71-
generatedKeys.addAll(rse.extractData(keys));
72-
} finally {
73-
JdbcUtils.closeResultSet(keys);
70+
if (JdbcUtils.supportsBatchUpdates(ps.getConnection())) {
71+
for (int i = 0; i < batchSize; i++) {
72+
bpss.setValues(ps, i);
73+
ps.addBatch();
74+
}
75+
int[] results = ps.executeBatch();
76+
storeGeneratedKeys(generatedKeyHolder).doInPreparedStatement(ps);
77+
return results;
78+
} else {
79+
List<Integer> rowsAffected = new ArrayList<>();
80+
for (int i = 0; i < batchSize; i++) {
81+
bpss.setValues(ps, i);
82+
rowsAffected.add(ps.executeUpdate());
7483
}
84+
int[] rowsAffectedArray = new int[rowsAffected.size()];
85+
storeGeneratedKeys(generatedKeyHolder).doInPreparedStatement(ps);
86+
for (int i = 0; i < rowsAffectedArray.length; i++) {
87+
rowsAffectedArray[i] = rowsAffected.get(i);
88+
}
89+
return rowsAffectedArray;
7590
}
76-
return results;
7791
};
7892
return jdbcOperations.execute(psc, preparedStatementCallback);
7993
}
8094

81-
@Nullable
82-
public int[] batchUpdate(String insertSql, SqlParameterSource[] sqlParameterSources,
83-
KeyHolder generatedKeyHolder, String[] keyColumnNames) {
84-
// TODO: This is largely duplicated from spring-jdbc and should be replaced with a call into
85-
// NamedParameterJdbcTemplate#batchUpdate once a method taking KeyHolder is added there.
86-
ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(insertSql);
87-
SqlParameterSource paramSource = sqlParameterSources[0];
88-
String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource);
89-
List<SqlParameter> declaredParameters = NamedParameterUtils.buildSqlParameterList(parsedSql, paramSource);
90-
PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(sqlToUse, declaredParameters);
91-
pscf.setReturnGeneratedKeys(true);
92-
pscf.setGeneratedKeysColumnNames(keyColumnNames);
93-
Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, null);
94-
PreparedStatementCreator psc = pscf.newPreparedStatementCreator(params);
95-
BatchPreparedStatementSetter bpss = new BatchPreparedStatementSetter() {
96-
@Override
97-
public void setValues(PreparedStatement ps, int i) throws SQLException {
98-
Object[] values = NamedParameterUtils.buildValueArray(parsedSql, sqlParameterSources[i], null);
99-
pscf.newPreparedStatementSetter(values).setValues(ps);
100-
}
101-
102-
@Override
103-
public int getBatchSize() {
104-
return sqlParameterSources.length;
105-
}
106-
};
107-
PreparedStatementCallback<int[]> preparedStatementCallback = ps -> {
108-
int batchSize = bpss.getBatchSize();
109-
for (int i = 0; i < batchSize; i++) {
110-
bpss.setValues(ps, i);
111-
ps.addBatch();
112-
}
113-
int[] results = ps.executeBatch();
114-
List<Map<String, Object>> generatedKeys = ((KeyHolder) generatedKeyHolder).getKeyList();
95+
private PreparedStatementCallback<Void> storeGeneratedKeys(KeyHolder generatedKeyHolder) {
96+
return ps -> {
97+
List<Map<String, Object>> generatedKeys = generatedKeyHolder.getKeyList();
11598
generatedKeys.clear();
11699
ResultSet keys = ps.getGeneratedKeys();
117100
if (keys != null) {
@@ -120,12 +103,12 @@ public int getBatchSize() {
120103
new RowMapperResultSetExtractor<>(new ColumnMapRowMapper(), 1);
121104
//noinspection ConstantConditions
122105
generatedKeys.addAll(rse.extractData(keys));
123-
} finally {
106+
}
107+
finally {
124108
JdbcUtils.closeResultSet(keys);
125109
}
126110
}
127-
return results;
111+
return null;
128112
};
129-
return jdbcOperations.execute(psc, preparedStatementCallback);
130113
}
131114
}

0 commit comments

Comments
 (0)