Cách thứ hai hiệu quả hơn một chút, nhưng cách tốt hơn nhiều là thực thi chúng theo lô:
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();
}
}
Tuy nhiên, bạn phụ thuộc vào việc triển khai trình điều khiển JDBC bao nhiêu lô bạn có thể thực thi cùng một lúc. Ví dụ, bạn có thể muốn thực thi chúng sau mỗi 1000 lô:
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.
}
}
}
}
Đối với môi trường đa luồng, bạn không cần phải lo lắng về điều này nếu bạn có và đóng kết nối và câu lệnh trong phạm vi ngắn nhất có thể bên trong cùng một khối phương thức theo thành ngữ JDBC thông thường sử dụng câu lệnh try-with-resources như được hiển thị trong các đoạn trên.
Nếu các lô đó là giao dịch, thì bạn muốn tắt tính năng tự động gửi kết nối và chỉ thực hiện giao dịch khi tất cả các lô kết thúc. Nếu không, nó có thể dẫn đến một cơ sở dữ liệu bẩn khi loạt lô đầu tiên thành công và sau đó thì không.
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
không thay đổi với trong vòng lặp? nếu truy vấn đó không thay đổi cho mỗi lần lặp lại của vòng lặp, thì tại sao bạn lại tạo một truy vấn mớiPreparedStatement
cho mỗi lần lặp (trong đoạn mã đầu tiên)? Có lý do gì để làm như vậy không?