CommencezCommencez gratuitement

Retour d'un livre

Vous êtes développeur pour le système de gestion de la Bibliothèque publique métropolitaine. La semaine dernière, un bogue critique a été découvert : quand le système plantait pendant un retour de livre, le prêt était marqué comme « retourné », mais le livre restait « emprunté » dans l'inventaire. Le livre demeurait ainsi indisponible pendant des semaines, jusqu'à ce que le personnel corrige la base de données manuellement.

Lorsqu'un livre est retourné, trois opérations doivent soit réussir ensemble, soit échouer ensemble :

  1. Mettre à jour l'enregistrement de prêt au statut « retourné ».
  2. Changer la disponibilité du livre de « emprunté » à « disponible ».
  3. Enregistrer une amende si le livre est retourné en retard.

Votre tâche consiste à mettre en place un contrôle de transaction adéquat pour assurer la cohérence des données.

Cette activité fait partie du cours

Interroger une base de données PostgreSQL en Java

Voir le cours

Instructions de l’exercice

  • Réglez autoCommit à 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 ce code d’exemple.

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