Merge 92734dbb0d
into 60b19278c0
This commit is contained in:
commit
e9e1b7dbd7
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package org.springframework.jdbc.core.namedparam;
|
package org.springframework.jdbc.core.namedparam;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
@ -586,4 +587,16 @@ public interface NamedParameterJdbcOperations {
|
||||||
int[] batchUpdate(String sql, SqlParameterSource[] batchArgs, KeyHolder generatedKeyHolder,
|
int[] batchUpdate(String sql, SqlParameterSource[] batchArgs, KeyHolder generatedKeyHolder,
|
||||||
String[] keyColumnNames);
|
String[] keyColumnNames);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the specified SQL update statement in multiple batches using the provided batch arguments.
|
||||||
|
* @param sql the SQL statement to execute
|
||||||
|
* @param batchArgs the collection of {@link SqlParameterSource} containing arguments for the query
|
||||||
|
* @param batchSize batch size
|
||||||
|
* @return a two-dimensional array containing results for each batch execution.
|
||||||
|
* (may also contain special JDBC-defined negative values for affected rows such as
|
||||||
|
* {@link java.sql.Statement#SUCCESS_NO_INFO}/{@link java.sql.Statement#EXECUTE_FAILED})
|
||||||
|
* @throws DataAccessException if there is any problem issuing the update
|
||||||
|
*/
|
||||||
|
int[][] batchUpdate(String sql, Collection<SqlParameterSource> batchArgs, int batchSize);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.springframework.jdbc.core.namedparam;
|
||||||
|
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
@ -423,6 +424,21 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations
|
||||||
}, generatedKeyHolder);
|
}, generatedKeyHolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[][] batchUpdate(String sql, Collection<SqlParameterSource> batchArgs, int batchSize) {
|
||||||
|
if (batchArgs.isEmpty() || batchSize <= 0) {
|
||||||
|
return new int[0][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
ParsedSql parsedSql = getParsedSql(sql);
|
||||||
|
SqlParameterSource sqlParameterSource = batchArgs.iterator().next();
|
||||||
|
PreparedStatementCreatorFactory pscf = getPreparedStatementCreatorFactory(parsedSql, sqlParameterSource);
|
||||||
|
|
||||||
|
return getJdbcOperations().batchUpdate(pscf.getSql(), batchArgs, batchSize, (ps, argument) -> {
|
||||||
|
@Nullable Object[] values = NamedParameterUtils.buildValueArray(parsedSql, argument, null);
|
||||||
|
pscf.newPreparedStatementSetter(values).setValues(ps);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a {@link PreparedStatementCreator} based on the given SQL and named parameters.
|
* Build a {@link PreparedStatementCreator} based on the given SQL and named parameters.
|
||||||
|
|
|
@ -53,6 +53,7 @@ import static org.mockito.Mockito.inOrder;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyNoInteractions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Rick Evans
|
* @author Rick Evans
|
||||||
|
@ -580,4 +581,104 @@ class NamedParameterJdbcTemplateTests {
|
||||||
verify(connection, atLeastOnce()).close();
|
verify(connection, atLeastOnce()).close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testMultipleBatchUpdateWithSqlParameterSource() throws Exception {
|
||||||
|
List<SqlParameterSource> ids = List.of(
|
||||||
|
new MapSqlParameterSource("id", 100),
|
||||||
|
new MapSqlParameterSource("id", 200),
|
||||||
|
new MapSqlParameterSource("id", 300),
|
||||||
|
new MapSqlParameterSource("id", 400),
|
||||||
|
new MapSqlParameterSource("id", 500)
|
||||||
|
);
|
||||||
|
|
||||||
|
int[] rowsAffected1 = new int[]{1, 2};
|
||||||
|
int[] rowsAffected2 = new int[]{3, 4};
|
||||||
|
int[] rowsAffected3 = new int[]{5};
|
||||||
|
|
||||||
|
given(preparedStatement.executeBatch()).willReturn(rowsAffected1, rowsAffected2, rowsAffected3);
|
||||||
|
given(connection.getMetaData()).willReturn(databaseMetaData);
|
||||||
|
|
||||||
|
namedParameterTemplate = new NamedParameterJdbcTemplate(new JdbcTemplate(dataSource, false));
|
||||||
|
|
||||||
|
int batchSize = 2;
|
||||||
|
|
||||||
|
int[][] actualRowsAffected = namedParameterTemplate.batchUpdate(
|
||||||
|
"UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = :id", ids, batchSize);
|
||||||
|
|
||||||
|
assertThat(actualRowsAffected.length).as("executed 3 batches").isEqualTo(3);
|
||||||
|
assertThat(actualRowsAffected[0]).isEqualTo(rowsAffected1);
|
||||||
|
assertThat(actualRowsAffected[1]).isEqualTo(rowsAffected2);
|
||||||
|
assertThat(actualRowsAffected[2]).isEqualTo(rowsAffected3);
|
||||||
|
|
||||||
|
verify(preparedStatement, times(5)).addBatch();
|
||||||
|
verify(connection, times(1)).prepareStatement("UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = ?");
|
||||||
|
verify(preparedStatement).setObject(1, 100);
|
||||||
|
verify(preparedStatement).setObject(1, 200);
|
||||||
|
verify(preparedStatement).setObject(1, 300);
|
||||||
|
verify(preparedStatement).setObject(1, 400);
|
||||||
|
verify(preparedStatement).setObject(1, 500);
|
||||||
|
verify(preparedStatement, atLeastOnce()).close();
|
||||||
|
verify(connection, atLeastOnce()).close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testMultipleBatchUpdateWithEmptySqlParameterSourceArg() {
|
||||||
|
namedParameterTemplate = new NamedParameterJdbcTemplate(new JdbcTemplate(dataSource, false));
|
||||||
|
|
||||||
|
int batchSize = 2;
|
||||||
|
|
||||||
|
int[][] actualRowsAffected = namedParameterTemplate.batchUpdate(
|
||||||
|
"UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = :id", Collections.emptyList(), batchSize);
|
||||||
|
|
||||||
|
assertThat(actualRowsAffected.length).as("executed 0 batches").isZero();
|
||||||
|
verifyNoInteractions(preparedStatement);
|
||||||
|
verifyNoInteractions(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testMultipleBatchUpdateWithSqlParameterSourceWithZeroBatchSize() {
|
||||||
|
namedParameterTemplate = new NamedParameterJdbcTemplate(new JdbcTemplate(dataSource, false));
|
||||||
|
|
||||||
|
int batchSize = 0;
|
||||||
|
|
||||||
|
int[][] actualRowsAffected = namedParameterTemplate.batchUpdate(
|
||||||
|
"UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = :id",
|
||||||
|
List.of(new MapSqlParameterSource("id", 100)),
|
||||||
|
batchSize);
|
||||||
|
|
||||||
|
assertThat(actualRowsAffected.length).as("executed 0 batches").isZero();
|
||||||
|
verifyNoInteractions(preparedStatement);
|
||||||
|
verifyNoInteractions(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testMultipleBatchUpdateWithSqlParameterSourceSmallerThanBatchSize() throws Exception {
|
||||||
|
List<SqlParameterSource> ids = List.of(
|
||||||
|
new MapSqlParameterSource("id", 100),
|
||||||
|
new MapSqlParameterSource("id", 200)
|
||||||
|
);
|
||||||
|
|
||||||
|
int[] rowsAffected = new int[]{1, 2};
|
||||||
|
|
||||||
|
given(preparedStatement.executeBatch()).willReturn(rowsAffected);
|
||||||
|
given(connection.getMetaData()).willReturn(databaseMetaData);
|
||||||
|
|
||||||
|
namedParameterTemplate = new NamedParameterJdbcTemplate(new JdbcTemplate(dataSource, false));
|
||||||
|
|
||||||
|
int batchSize = 3;
|
||||||
|
|
||||||
|
int[][] actualRowsAffected = namedParameterTemplate.batchUpdate(
|
||||||
|
"UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = :id", ids, batchSize);
|
||||||
|
|
||||||
|
assertThat(actualRowsAffected.length).as("executed 1 batch").isEqualTo(1);
|
||||||
|
assertThat(actualRowsAffected[0]).isEqualTo(rowsAffected);
|
||||||
|
|
||||||
|
verify(preparedStatement, times(2)).addBatch();
|
||||||
|
verify(connection, times(1)).prepareStatement("UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = ?");
|
||||||
|
verify(preparedStatement).setObject(1, 100);
|
||||||
|
verify(preparedStatement).setObject(1, 200);
|
||||||
|
verify(preparedStatement, atLeastOnce()).close();
|
||||||
|
verify(connection, atLeastOnce()).close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue