TransactionRequiredException Error

1. Ikhtisar

Dalam tutorial ini, kita akan memeriksa penyebab kesalahan TransactionRequiredException dan cara mengatasinya.

2. TransactionRequiredException

Kesalahan ini biasanya terjadi saat kami mencoba melakukan operasi database yang mengubah database tanpa transaksi .

Misalnya, mencoba memperbarui catatan tanpa transaksi:

Query updateQuery = session.createQuery("UPDATE Post p SET p.title = ?1, p.body = ?2 WHERE p.id = ?3"); updateQuery.setParameter(1, title); updateQuery.setParameter(2, body); updateQuery.setParameter(3, id); updateQuery.executeUpdate();

Akan memunculkan pengecualian dengan pesan di sepanjang baris berikut:

... javax.persistence.TransactionRequiredException: Executing an update/delete query at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1586) ...

3. Melakukan Transaksi

Solusi yang jelas adalah membungkus operasi pengubah database apa pun dalam sebuah transaksi:

Transaction txn = session.beginTransaction(); Query updateQuery = session.createQuery("UPDATE Post p SET p.title = ?1, p.body = ?2 WHERE p.id = ?3"); updateQuery.setParameter(1, title); updateQuery.setParameter(2, body); updateQuery.setParameter(3, id); updateQuery.executeUpdate(); txn.commit();

Dalam potongan kode di atas, kami memulai dan melakukan transaksi secara manual. Meskipun dalam lingkungan Spring Boot, kita dapat melakukannya dengan menggunakan anotasi @Transactional .

4. Dukungan Transaksi di Musim Semi

Jika kita menginginkan kontrol yang lebih halus, kita dapat menggunakan TransactionTemplate Spring . Karena ini memungkinkan programmer untuk memicu persistensi suatu objek segera sebelum melanjutkan dengan eksekusi kode suatu metode.

Misalnya, kita ingin mengupdate postingan sebelum mengirim email notifikasi:

public void update() { entityManager.createQuery("UPDATE Post p SET p.title = ?2, p.body = ?3 WHERE p.id = ?1") // parameters .executeUpdate(); sendEmail(); }

Menerapkan @Transactional ke metode di atas dapat menyebabkan email terkirim meskipun ada pengecualian dalam proses pembaruan. Ini karena transaksi hanya akan dilakukan saat metode keluar dan akan kembali ke pemanggil.

Oleh karena itu, memperbarui posting dalam TransactionTemplate akan mencegah skenario ini karena akan segera menjalankan operasi:

public void update() { transactionTemplate.execute(transactionStatus -> { entityManager.createQuery("UPDATE Post p SET p.title = ?2, p.body = ?3 WHERE p.id = ?1") // parameters .executeUpdate(); transactionStatus.flush(); return null; }); sendEmail(); }

5. Kesimpulan

Kesimpulannya, umumnya merupakan praktik yang baik untuk menggabungkan operasi database dalam sebuah transaksi. Ini membantu dalam mencegah kerusakan data. Kode sumber lengkap tersedia di Github.