Samedis Club de lecture
La Metropolitan Public Library organise les « Samedis Club de lecture », un événement extrêmement populaire où 30 à 40 membres arrivent à 10 h pour emprunter leurs lectures du mois. Le système actuel traite chaque prêt individuellement avec l’auto-commit activé, ce qui engendre deux problèmes critiques :
- Incohérence des données : le mois dernier, le système a planté pendant le traitement d’un emprunt de quatre livres par un membre. Deux livres ont été enregistrés comme empruntés, mais pas les deux autres, provoquant des écarts d’inventaire et la frustration des usagers.
- Goulot d’étranglement des performances : traiter chaque prêt comme une transaction distincte prend 15 à 20 minutes, entraînant de longues files d’attente et des équipes de bibliothèque mécontentes.
Votre mission est de mettre en place un traitement par lots avec contrôle de transaction.
Cet exercice fait partie du cours
Interroger une base de données PostgreSQL en Java
Instructions
- Définissez
autoCommitsurfalsepour activer le contrôle manuel des transactions à la ligne 32. - Ajoutez plusieurs prêts au lot à la ligne 43.
- Validez la transaction si toutes les opérations réussissent à la ligne 49.
Exercice interactif pratique
Essayez cet exercice en complétant cet exemple de code.
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;
}
}
}
}