ÎncepețiÎncepe gratuit

Returnarea unei cărți

Ești un dezvoltator pentru sistemul de management al Bibliotecii Publice Metropolitane. Săptămâna trecută, a fost descoperit un bug critic: atunci când sistemul se bloca în timpul returnării unei cărți, împrumutul era marcat ca „returnat", însă cartea rămânea cu statusul „împrumutată" în inventar. Astfel, cartea devenea indisponibilă timp de câteva săptămâni, până când personalul corecta manual baza de date.

Atunci când o carte este returnată, trei operațiuni trebuie să reușească împreună sau să eșueze împreună:

  1. Actualizarea înregistrării împrumutului cu statusul „returnat".
  2. Schimbarea disponibilității cărții din „împrumutată" în „disponibilă".
  3. Înregistrarea unei amenzi dacă volumul este returnat cu întârziere.

Sarcina ta este să implementezi un control adecvat al tranzacțiilor pentru a asigura consistența datelor.

Acest exercițiu face parte din cursul

Interogarea unei baze de date PostgreSQL în Java

Vezi cursul

Instrucțiuni pentru exercițiu

  • Setează autoCommit la false la început, în linia 26.
  • Confirmă tranzacția dacă toate operațiunile reușesc, în linia 59.
  • Dacă oricare dintre operațiuni eșuează, anulează tranzacția în linia 66.

Exercițiu interactiv practic

Încearcă acest exercițiu completând acest cod de exemplu.

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;
        }
    }
}
Editează și rulează codul