Book Club Saturdays
Thư viện Công cộng Metropolitan tổ chức "Book Club Saturdays", một sự kiện cực kỳ hút khách nơi 30–40 thành viên đến lúc 10 giờ sáng để mượn sách theo lựa chọn hằng tháng. Hệ thống hiện tại xử lý từng khoản mượn riêng lẻ với auto-commit bật, dẫn đến hai vấn đề nghiêm trọng:
- Không nhất quán dữ liệu: Tháng trước, hệ thống bị treo khi đang xử lý lượt mượn bốn cuốn của một thành viên. Hai cuốn được ghi nhận là đã mượn, nhưng hai cuốn còn lại thì không, gây sai lệch tồn kho và làm người dùng bức xúc.
- Nút thắt hiệu năng: Xử lý mỗi khoản mượn như một giao dịch cơ sở dữ liệu riêng mất 15–20 phút, tạo hàng đợi dài và khiến nhân viên thư viện không hài lòng.
Nhiệm vụ của bạn là triển khai xử lý theo lô (batch processing) với kiểm soát giao dịch (transaction).
Bài tập này là một phần của khóa học
Truy vấn cơ sở dữ liệu PostgreSQL trong Java
Hướng dẫn bài tập
- Đặt
autoCommitthànhfalseđể bật kiểm soát giao dịch thủ công ở dòng 32. - Thêm nhiều khoản mượn vào lô ở dòng 43.
- Commit giao dịch nếu tất cả thao tác đều thành công ở dòng 49.
Bài tập tương tác thực hành trực tiếp
Hãy thử làm bài tập này bằng cách hoàn thành đoạn mã mẫu này.
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;
}
}
}
}