Второй способ немного более эффективен, но гораздо лучше выполнять их партиями:
public void executeBatch(List<Entity> entities) throws SQLException {
try (
Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(SQL);
) {
for (Entity entity : entities) {
statement.setObject(1, entity.getSomeProperty());
// ...
statement.addBatch();
}
statement.executeBatch();
}
}
Однако вы зависите от реализации драйвера JDBC, сколько пакетов вы можете выполнить одновременно. Например, вы можете захотеть выполнять их каждые 1000 пакетов:
public void executeBatch(List<Entity> entities) throws SQLException {
try (
Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(SQL);
) {
int i = 0;
for (Entity entity : entities) {
statement.setObject(1, entity.getSomeProperty());
// ...
statement.addBatch();
i++;
if (i % 1000 == 0 || i == entities.size()) {
statement.executeBatch(); // Execute every 1000 items.
}
}
}
}
Что касается многопоточных сред, вам не нужно беспокоиться об этом, если вы приобретете и закроете соединение и оператор в кратчайшей возможной области внутри одного и того же блока метода в соответствии с обычной идиомой JDBC с использованием оператора try-with-resources, как показано на выше фрагменты.
Если эти пакеты являются транзакционными, то вы хотите отключить автоматическую фиксацию соединения и фиксировать транзакцию только после завершения всех пакетов. В противном случае это может привести к загрязнению базы данных, когда первая группа пакетов прошла успешно, а вторая - нет.
public void executeBatch(List<Entity> entities) throws SQLException {
try (Connection connection = dataSource.getConnection()) {
connection.setAutoCommit(false);
try (PreparedStatement statement = connection.prepareStatement(SQL)) {
// ...
try {
connection.commit();
} catch (SQLException e) {
connection.rollback();
throw e;
}
}
}
}
sql
не меняется в цикле? если этот запрос не меняется для каждой итерации цикла, то почему вы создаете новыйPreparedStatement
для каждой итерации (в первом фрагменте кода)? Есть ли причина для этого?