วิธีที่สองนั้นมีประสิทธิภาพมากขึ้นเล็กน้อย แต่วิธีที่ดีกว่ามากคือการดำเนินการเป็นกลุ่ม:
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();
}
}
อย่างไรก็ตามคุณขึ้นอยู่กับการใช้งานไดรเวอร์ JDBC ว่าคุณสามารถดำเนินการได้กี่ชุดพร้อมกัน ตัวอย่างเช่นคุณอาจต้องการดำเนินการทุก 1,000 แบทช์:
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();
}
}
}
}
สำหรับสภาพแวดล้อมแบบมัลติเธรดคุณไม่จำเป็นต้องกังวลเกี่ยวกับเรื่องนี้หากคุณได้รับและปิดการเชื่อมต่อและคำสั่งในขอบเขตที่สั้นที่สุดที่เป็นไปได้ภายในบล็อกวิธีการเดียวกันตามสำนวน JDBC ปกติโดยใช้คำสั่งtry-with-resourcesดังที่แสดงใน ด้านบนตัวอย่าง
หากแบทช์เหล่านั้นเป็นธุรกรรมคุณต้องการปิดการสื่อสารอัตโนมัติของการเชื่อมต่อและทำธุรกรรมเมื่อแบทช์ทั้งหมดเสร็จสิ้นเท่านั้น มิฉะนั้นอาจส่งผลให้ฐานข้อมูลสกปรกเมื่อชุดงานชุดแรกสำเร็จและไม่สำเร็จในภายหลัง
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
จะไม่เปลี่ยนในลูป? หากแบบสอบถามนั้นไม่เปลี่ยนแปลงสำหรับการวนซ้ำแต่ละครั้งเหตุใดคุณจึงสร้างใหม่PreparedStatement
สำหรับการวนซ้ำแต่ละครั้ง (ในข้อมูลโค้ดแรก) มีเหตุผลอะไรในการทำเช่นนั้น?