Drugi sposób jest odrobinę bardziej wydajny, ale znacznie lepszym sposobem jest wykonywanie ich partiami:
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();
}
}
Jesteś jednak zależny od implementacji sterownika JDBC, ile partii można wykonać naraz. Możesz na przykład chcieć wykonywać je co 1000 partii:
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.
}
}
}
}
Jeśli chodzi o środowiska wielowątkowe, nie musisz się tym martwić, jeśli uzyskasz i zamkniesz połączenie i instrukcję w najkrótszym możliwym zakresie w tym samym bloku metody zgodnie z normalnym idiomem JDBC przy użyciu instrukcji try-with-resources , jak pokazano w powyżej fragmentów.
Jeśli te partie są transakcyjne, chcesz wyłączyć automatyczne zatwierdzanie połączenia i zatwierdzać transakcję dopiero po zakończeniu wszystkich partii. W przeciwnym razie może to spowodować brudną bazę danych, gdy pierwsza seria partii zakończy się powodzeniem, a później nie.
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
nie zmienia się z w pętli? jeśli to zapytanie nie zmienia się dla każdej iteracji pętli, to dlaczego tworzysz nowePreparedStatement
dla każdej iteracji (w pierwszym fragmencie kodu)? Czy jest jakiś powód, aby to robić?