Il secondo modo è un po 'più efficiente, ma un modo molto migliore è eseguirli in batch:
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();
}
}
Tuttavia, dipendi dall'implementazione del driver JDBC quanti batch potresti eseguire contemporaneamente. Ad esempio, potresti voler eseguirli ogni 1000 batch:
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.
}
}
}
}
Per quanto riguarda gli ambienti multithread, non devi preoccuparti di questo se acquisisci e chiudi la connessione e l'istruzione nel più breve ambito possibile all'interno dello stesso blocco del metodo secondo il normale idioma JDBC usando l' istruzione try-with-resources come mostrato in sopra i frammenti.
Se questi batch sono transazionali, disattivare il commit automatico della connessione e eseguire il commit della transazione solo quando tutti i batch sono terminati. Altrimenti potrebbe risultare in un database sporco quando il primo gruppo di batch è riuscito e il secondo no.
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
non cambia con nel ciclo? se quella query non cambia per ogni iterazione del ciclo, allora perché ne crei una nuovaPreparedStatement
per ogni iterazione (nel primo frammento di codice)? C'è qualche motivo per farlo?