Bắt đầu ngayBắt đầu miễn phí

Trả sách

Bạn là lập trình viên cho hệ thống quản lý của Thư viện Công cộng Metropolitan. Tuần trước, một lỗi nghiêm trọng đã được phát hiện: khi hệ thống bị sập trong lúc trả sách, bản ghi mượn được đánh dấu là "returned" nhưng cuốn sách vẫn ở trạng thái "checked-out" trong kho. Điều này khiến sách không thể được mượn trong nhiều tuần cho đến khi nhân viên sửa dữ liệu thủ công.

Khi một cuốn sách được trả, ba thao tác sau phải cùng thành công hoặc cùng thất bại:

  1. Cập nhật bản ghi mượn sang trạng thái "returned".
  2. Chuyển tình trạng sẵn sàng của sách từ "checked-out" sang "available".
  3. Ghi nhận tiền phạt nếu sách trả trễ.

Nhiệm vụ của bạn là triển khai kiểm soát giao dịch phù hợp để đảm bảo tính nhất quán dữ liệu.

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

Xem khóa học

Hướng dẫn bài tập

  • Đặt autoCommit thành false ở đầu, tại dòng 26.
  • COMMIT giao dịch nếu tất cả thao tác thành công ở dòng 59.
  • Nếu bất kỳ thao tác nào thất bại, ROLLBACK giao dịch ở dòng 66.

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 BookReturnProcessor {
    public static void main(String[] args) {
        int loanId = 1;
        int bookId = 5;
        LocalDate dueDate = LocalDate.now().minusDays(2);
        
        try {
            boolean success = processBookReturn(loanId, bookId, dueDate);
            if (success) {
                System.out.println("Book return processed successfully.");
            } else {
                System.out.println("Book return processing failed.");
            }
        } catch (SQLException e) {
            System.err.println("Database error: " + e.getMessage());
        }
    }
    
    public static boolean processBookReturn(int loanId, int bookId, LocalDate dueDate) throws SQLException {
        Connection conn = null;
        try {
            HikariDataSource ds = HikariSetup.createDataSource();
            conn = ds.getConnection();
            
            // Start transaction by setting autoCommit to false
            conn.____(____);
            
            String updateLoanSQL = "UPDATE loans SET status = 'returned', return_date = ? WHERE loan_id = ?";
            try (PreparedStatement pstmt = conn.prepareStatement(updateLoanSQL)) {
                pstmt.setDate(1, java.sql.Date.valueOf(LocalDate.now()));
                pstmt.setInt(2, loanId);
                pstmt.executeUpdate();
            }
            
            String updateBookSQL = "UPDATE books SET status = 'available' WHERE book_id = ?";
            try (PreparedStatement pstmt = conn.prepareStatement(updateBookSQL)) {
                pstmt.setInt(1, bookId);
                pstmt.executeUpdate();
            }
            
            LocalDate today = LocalDate.now();
            if (today.isAfter(dueDate)) {
                long daysLate = ChronoUnit.DAYS.between(dueDate, today);
                double fineAmount = daysLate * 0.50;
                
                String insertFineSQL = "INSERT INTO fines (loan_id, amount, reason, date_assessed) VALUES (?, ?, ?, ?)";
                try (PreparedStatement pstmt = conn.prepareStatement(insertFineSQL)) {
                    pstmt.setInt(1, loanId);
                    pstmt.setDouble(2, fineAmount);
                    pstmt.setString(3, "Book returned " + daysLate + " days late");
                    pstmt.setDate(4, java.sql.Date.valueOf(today));
                    pstmt.executeUpdate();
                }
                
                System.out.println("Fine created: $" + fineAmount + " for loan " + loanId);
            }
            
            // Commit the transaction
            conn.____();
            
            return true;
            
        } catch (SQLException e) {
            // Roll back the transaction if an error occurs
            if (conn != null) {
                conn.____();
            }
            System.err.println("Error processing return: " + e.getMessage());
            return false;
        }
    }
}
Chỉnh sửa và Chạy Mã