Cara kedua sedikit lebih efisien, tetapi cara yang jauh lebih baik adalah mengeksekusinya secara berkelompok:
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();
}
}
Namun, Anda bergantung pada implementasi driver JDBC, berapa banyak batch yang dapat Anda jalankan sekaligus. Misalnya, Anda mungkin ingin mengeksekusinya setiap 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.
}
}
}
}
Mengenai lingkungan multithread, Anda tidak perlu khawatir tentang hal ini jika Anda memperoleh dan menutup koneksi dan pernyataan dalam cakupan sesingkat mungkin di dalam blok metode yang sama sesuai dengan idiom JDBC normal menggunakan pernyataan coba-dengan-sumber daya seperti yang ditunjukkan di cuplikan di atas.
Jika kumpulan tersebut bersifat transaksional, maka Anda ingin menonaktifkan koneksi otomatis dan hanya melakukan transaksi saat semua kumpulan selesai. Jika tidak, hal itu dapat mengakibatkan database kotor ketika kelompok pertama dari batch berhasil dan kemudian tidak.
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
tidak berubah dengan in the loop? jika kueri itu tidak berubah untuk setiap iterasi loop, lalu mengapa Anda membuat yang baruPreparedStatement
untuk setiap iterasi (di cuplikan kode pertama)? Apakah ada alasan untuk melakukannya?