Book Club Saturdays
ห้องสมุดสาธารณะ Metropolitan จัดกิจกรรม "Book Club Saturdays" ซึ่งได้รับความนิยมอย่างมาก โดยสมาชิก 30-40 คนจะมาถึงในเวลา 10.00 น. เพื่อยืมหนังสือที่คัดเลือกประจำเดือน ระบบปัจจุบันประมวลผลการยืมทีละรายการโดยเปิดใช้งาน auto-commit ซึ่งก่อให้เกิดปัญหาสำคัญ 2 ประการ ดังนี้
- ความไม่สอดคล้องของข้อมูล: เดือนที่แล้ว ระบบขัดข้องระหว่างประมวลผลการยืมหนังสือ 4 เล่มของสมาชิกรายหนึ่ง หนังสือ 2 เล่มถูกบันทึกว่ายืมแล้ว แต่อีก 2 เล่มไม่ได้รับการบันทึก ส่งผลให้ข้อมูลสินค้าคงคลังคลาดเคลื่อนและสมาชิกเกิดความไม่พอใจ
- ปัญหาด้านประสิทธิภาพ: การประมวลผลการยืมแต่ละรายการเป็น transaction แยกต่างหากใช้เวลา 15-20 นาที ทำให้เกิดคิวยาวและเจ้าหน้าที่ห้องสมุดทำงานลำบาก
ภารกิจของคุณคือนำ batch processing มาใช้ร่วมกับการควบคุม transaction
แบบฝึกหัดนี้เป็นส่วนหนึ่งของหลักสูตร
การคิวรีฐานข้อมูล PostgreSQL ด้วย Java
คำแนะนำการฝึกหัด
- กำหนดให้
autoCommitเป็นfalseเพื่อเปิดใช้งานการควบคุม transaction ด้วยตนเองใน บรรทัดที่ 32 - เพิ่มรายการยืมหลายรายการเข้า batch ใน บรรทัดที่ 43
- Commit transaction หากทุกการดำเนินการสำเร็จใน บรรทัดที่ 49
แบบฝึกหัดเชิงโต้ตอบแบบลงมือทำ
ลองทำแบบฝึกหัดนี้โดยเติมโค้ดตัวอย่างนี้ให้สมบูรณ์
public class BatchLoanProcessor {
private static final String DB_URL = "jdbc:postgresql://localhost:5432/library_db";
private static final String USERNAME = "postgres";
private static final String PASSWORD = "postgres";
public static void main(String[] args) {
Object[][] loanData = {
{1, 1, LocalDate.now(), LocalDate.now().plusDays(14), "borrowed"},
{2, 2, LocalDate.now(), LocalDate.now().plusDays(14), "borrowed"},
{3, 3, LocalDate.now(), LocalDate.now().plusDays(7), "borrowed"},
{4, 1, LocalDate.now(), LocalDate.now().plusDays(14), "borrowed"}
};
try {
boolean success = processBatchLoans(loanData);
if (success) {
System.out.println("All loans were processed successfully.");
} else {
System.out.println("Loan processing failed. Transaction was rolled back.");
}
} catch (SQLException e) {
System.err.println("Database error: " + e.getMessage());
e.printStackTrace();
}
}
public static boolean processBatchLoans(Object[][] loanData) throws SQLException {
String insertSQL = "INSERT INTO loans (book_id, member_id, loan_date, due_date, status) VALUES (?, ?, ?, ?, ?)";
try (Connection conn = DriverManager.getConnection(DB_URL, USERNAME, PASSWORD)) {
// Set autoCommit to false
conn.____(____);
try (PreparedStatement pstmt = conn.prepareStatement(insertSQL)) {
for (Object[] loan : loanData) {
pstmt.setInt(1, (Integer) loan[0]);
pstmt.setInt(2, (Integer) loan[1]);
pstmt.setDate(3, java.sql.Date.valueOf((LocalDate) loan[2]));
pstmt.setDate(4, java.sql.Date.valueOf((LocalDate) loan[3]));
pstmt.setString(5, (String) loan[4]);
// Add to batch
pstmt.____();
}
int[] results = pstmt.executeBatch();
// Commit the transaction if all operations are successful
conn.____();
return true;
} catch (SQLException e) {
conn.rollback();
System.err.println("Error during batch processing: " + e.getMessage());
return false;
}
}
}
}