ÎncepețiÎncepe gratuit

Sâmbetele Clubului de Carte

Biblioteca Publică Metropolitană organizează „Sâmbetele Clubului de Carte", un eveniment extrem de popular la care 30-40 de membri sosesc la ora 10:00 pentru a împrumuta selecțiile lunare. Sistemul actual procesează fiecare împrumut individual, cu auto-commit activat, ceea ce generează două probleme critice:

  1. Inconsistența datelor: Luna trecută, sistemul s-a blocat în timp ce procesa împrumutarea a patru cărți de către un membru. Două cărți au fost înregistrate ca împrumutate, celelalte două nu, cauzând discrepanțe în inventar și nemulțumiri în rândul utilizatorilor.
  2. Blocaj de performanță: Procesarea fiecărui împrumut ca o tranzacție separată durează 15-20 de minute, generând cozi lungi și personal nemulțumit.

Misiunea ta este să implementezi procesarea batch cu control al tranzacțiilor.

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 pentru a activa controlul manual al tranzacțiilor în linia 32.
  • Adaugă mai multe împrumuturi în batch în linia 43.
  • Confirmă tranzacția dacă toate operațiunile s-au finalizat cu succes în linia 49.

Exercițiu interactiv practic

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

public class BatchLoanProcessor {
    private static final String DB_URL = "jdbc:postgresql://localhost:5432/library_db";
    private static final String USERNAME = "postgres";
    private static final String PASSWORD = "postgres";
    
    public static void main(String[] args) {
        Object[][] loanData = {
            {1, 1, LocalDate.now(), LocalDate.now().plusDays(14), "borrowed"},
            {2, 2, LocalDate.now(), LocalDate.now().plusDays(14), "borrowed"},
            {3, 3, LocalDate.now(), LocalDate.now().plusDays(7), "borrowed"},
            {4, 1, LocalDate.now(), LocalDate.now().plusDays(14), "borrowed"}
        };
        
        try {
            boolean success = processBatchLoans(loanData);
            if (success) {
                System.out.println("All loans were processed successfully.");
            } else {
                System.out.println("Loan processing failed. Transaction was rolled back.");
            }
        } catch (SQLException e) {
            System.err.println("Database error: " + e.getMessage());
            e.printStackTrace();
        }
    }
    
    public static boolean processBatchLoans(Object[][] loanData) throws SQLException {
        String insertSQL = "INSERT INTO loans (book_id, member_id, loan_date, due_date, status) VALUES (?, ?, ?, ?, ?)";
        
        try (Connection conn = DriverManager.getConnection(DB_URL, USERNAME, PASSWORD)) {
            // Set autoCommit to false
            conn.____(____);
            
            try (PreparedStatement pstmt = conn.prepareStatement(insertSQL)) {
                for (Object[] loan : loanData) {
                    pstmt.setInt(1, (Integer) loan[0]);  
                    pstmt.setInt(2, (Integer) loan[1]);  
                    pstmt.setDate(3, java.sql.Date.valueOf((LocalDate) loan[2]));  
                    pstmt.setDate(4, java.sql.Date.valueOf((LocalDate) loan[3]));  
                    pstmt.setString(5, (String) loan[4]);  
                    
                    // Add to batch
                    pstmt.____();
                }
                
                int[] results = pstmt.executeBatch();
                                
                // Commit the transaction if all operations are successful
                conn.____();
                
                return true;
            } catch (SQLException e) {
                conn.rollback();
                
                System.err.println("Error during batch processing: " + e.getMessage());
                return false;
            }
        }
    }
}
Editează și rulează codul