Book Club Saturdays
Perpustakaan Umum Metropolitan menyelenggarakan "Book Club Saturdays", sebuah acara yang sangat populer di mana 30–40 anggota datang pukul 10 pagi untuk meminjam pilihan bulanan mereka. Sistem saat ini memproses setiap peminjaman secara terpisah dengan auto-commit aktif, sehingga menimbulkan dua masalah kritis:
- Ketidakkonsistenan data: Bulan lalu, sistem mengalami crash saat memproses peminjaman empat buku milik seorang anggota. Dua buku tercatat sebagai dipinjam, tetapi dua lainnya tidak, sehingga menimbulkan ketidaksesuaian inventaris dan membuat pemustaka frustrasi.
- Kemacetan kinerja: Memproses setiap peminjaman sebagai transaksi basis data terpisah membutuhkan waktu 15–20 menit, menyebabkan antrean panjang dan membuat staf perpustakaan kewalahan.
Misi Anda adalah menerapkan pemrosesan batch dengan kendali transaksi.
Latihan ini adalah bagian dari kursus
Melakukan Query ke Basis Data PostgreSQL di Java
Petunjuk latihan
- Atur
autoCommitkefalseuntuk mengaktifkan kendali transaksi manual pada baris 32. - Tambahkan beberapa peminjaman ke batch pada baris 43.
- Commit transaksi jika semua operasi berhasil pada baris 49.
Latihan interaktif praktis
Cobalah latihan ini dengan menyelesaikan kode contoh berikut.
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;
}
}
}
}