CommencerCommencer gratuitement

Retour d’un livre

Vous êtes développeur du système de gestion de la Metropolitan Public Library. La semaine dernière, un bogue critique a été découvert : lorsque le système plantait pendant un retour de livre, l’emprunt passait à l’état « returned », mais le livre restait « checked-out » dans l’inventaire. Le livre devenait alors indisponible pendant des semaines, jusqu’à ce que le personnel corrige la base de données manuellement.

Lorsqu’un livre est rendu, trois opérations doivent réussir ou échouer ensemble :

  1. Mettre à jour l’enregistrement d’emprunt avec le statut « returned ».
  2. Passer la disponibilité du livre de « checked-out » à « available ».
  3. Enregistrer une amende si le livre est rendu en retard.

Votre mission est de mettre en place un contrôle de transaction approprié pour garantir la cohérence des données.

Cet exercice fait partie du cours

Interroger une base de données PostgreSQL en Java

Afficher le cours

Instructions

  • Définissez autoCommit sur false au début à la ligne 26.
  • Validez la transaction si toutes les opérations réussissent à la ligne 59.
  • Si une opération échoue, annulez la transaction à la ligne 66.

Exercice interactif pratique

Essayez cet exercice en complétant cet exemple de code.

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;
        }
    }
}
Modifier et exécuter le code