Aan de slagGa gratis aan de slag

Een boek inleveren

Je bent ontwikkelaar voor het beheersysteem van de Metropolitan Public Library. Vorige week werd er een kritieke bug ontdekt: wanneer het systeem crashte tijdens het inleveren van een boek, werd de lening als "returned" gemarkeerd, maar bleef het boek in de inventaris op "checked-out" staan. Daardoor was het boek wekenlang niet beschikbaar totdat medewerkers de database handmatig corrigeerden.

Wanneer een boek wordt ingeleverd, moeten drie bewerkingen samen slagen of samen falen:

  1. Werk het leningrecord bij naar de status "returned".
  2. Verander de beschikbaarheid van het boek van "checked-out" naar "available".
  3. Registreer een boete als het boek te laat is ingeleverd.

Jouw taak is om correcte transactiebesturing te implementeren om gegevensconsistentie te waarborgen.

Deze oefening maakt deel uit van de cursus

Query's uitvoeren op een PostgreSQL-database in Java

Cursus bekijken

Oefeninstructies

  • Zet autoCommit op false helemaal aan het begin op regel 26.
  • Commit de transactie als alle bewerkingen slagen op regel 59.
  • Als een bewerking faalt, rol de transactie terug op regel 66.

Praktische interactieve oefening

Probeer deze oefening eens door deze voorbeeldcode in te vullen.

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;
        }
    }
}
Code bewerken en uitvoeren