Bir kitabı iade etme
Metropolitan Halk Kütüphanesi'nin yönetim sistemi için geliştirici olarak çalışıyorsun. Geçen hafta kritik bir hata keşfedildi: Sistem, bir kitap iadesi sırasında çöktüğünde, ödünç alma kaydı "returned" olarak işaretleniyordu ancak envanterde kitap hâlâ "checked-out" görünüyordu. Bu da, personel veritabanını elle düzeltene kadar kitabın haftalarca kullanılamaz kalmasına yol açtı.
Bir kitap iade edildiğinde, üç işlemin birlikte başarıyla tamamlanması ya da birlikte başarısız olması gerekir:
- Ödünç alma kaydını "returned" durumuna güncelle.
- Kitabın uygunluk durumunu "checked-out" değerinden "available" değerine değiştir.
- Kitap geç iade edildiyse bir ceza kaydı oluştur.
Görevin, veri tutarlılığını sağlamak için doğru işlem (transaction) kontrolünü uygulamak.
Bu egzersiz, kursun bir parçasıdır
Java ile PostgreSQL Veritabanına Sorgu Yazma
Egzersiz talimatları
- 26. satırda başta
autoCommitdeğerinifalseyap. - Tüm işlemler başarılı olursa 59. satırda transaction'ı commit et.
- Herhangi bir işlem başarısız olursa 66. satırda transaction'ı geri al (rollback).
Uygulamalı etkileşimli egzersiz
Bu egzersizi bu örnek kodu tamamlayarak deneyin.
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;
}
}
}