La deuxième façon est un peu plus efficace, mais une bien meilleure façon est de les exécuter par lots:
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();
}
}
Vous dépendez cependant de l'implémentation du pilote JDBC du nombre de lots que vous pouvez exécuter à la fois. Vous pouvez par exemple vouloir les exécuter tous les 1000 lots:
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.
}
}
}
}
En ce qui concerne les environnements multithread, vous n'avez pas à vous en soucier si vous acquérez et fermez la connexion et l'instruction dans la plus courte portée possible à l'intérieur du même bloc de méthode selon l'idiome JDBC normal en utilisant l' instruction try-with-resources comme indiqué dans au-dessus des extraits.
Si ces lots sont transactionnels, vous souhaitez désactiver la validation automatique de la connexion et ne valider la transaction que lorsque tous les lots sont terminés. Sinon, cela peut entraîner une base de données sale lorsque le premier groupe de lots a réussi et le dernier non.
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
ne change pas avec dans la boucle? si cette requête ne change pas pour chaque itération de la boucle, alors pourquoi en créez-vous une nouvellePreparedStatement
pour chaque itération (dans le premier extrait de code)? Y a-t-il une raison de le faire?