A segunda maneira é um pouco mais eficiente, mas uma maneira muito melhor é executá-los em lotes:
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();
}
}
No entanto, você depende da implementação do driver JDBC de quantos lotes pode executar de uma vez. Você pode, por exemplo, querer executá-los a cada 1000 lotes:
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.
}
}
}
}
Quanto aos ambientes multithread, você não precisa se preocupar com isso se adquirir e fechar a conexão e a instrução no menor escopo possível dentro do mesmo bloco de método de acordo com o idioma JDBC normal usando a instrução try-with-resources conforme mostrado em trechos acima.
Se esses lotes forem transacionais, você gostaria de desligar o autocommit da conexão e apenas confirmar a transação quando todos os lotes forem concluídos. Caso contrário, pode resultar em um banco de dados sujo quando o primeiro grupo de lotes for bem-sucedido e o posterior não.
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
não muda com no loop? se essa consulta não muda para cada iteração do loop, por que você está criando uma novaPreparedStatement
para cada iteração (no primeiro trecho de código)? Existe algum motivo para isso?