Untuk Spring Data 1.6 atau lebih baru
@Lock
didukung pada metode CRUD pada versi 1.6 Spring Data JPA (sebenarnya, sudah ada tonggak sejarah
tersedia). Lihat tiket
ini untuk lebih jelasnya.
Dengan versi tersebut Anda cukup mendeklarasikan sebagai berikut:
interface WidgetRepository extends Repository<Widget, Long> {
@Lock(LockModeType.PESSIMISTIC_WRITE)
Widget findOne(Long id);
}
Ini akan menyebabkan bagian implementasi CRUD dari proxy repositori pendukung untuk menerapkan LockModeType yang dikonfigurasi ke find(…)
panggil EntityManager
.
Sebaliknya,
Untuk versi Spring Data 1.6 sebelumnya
Spring Data pesimis @Lock
anotasi hanya berlaku (seperti yang Anda tunjukkan) untuk kueri. Tidak ada anotasi yang saya tahu yang dapat memengaruhi seluruh transaksi. Anda dapat membuat findByOnePessimistic
metode yang memanggil findByOne
dengan kunci pesimis atau Anda dapat mengubah findByOne
untuk selalu mendapatkan kunci pesimis.
Jika Anda ingin menerapkan solusi Anda sendiri, Anda mungkin bisa. Di bawah kap @Lock
anotasi diproses oleh LockModePopulatingMethodIntercceptor
yang melakukan hal berikut:
TransactionSynchronizationManager.bindResource(method, lockMode == null ? NULL : lockMode);
Anda dapat membuat beberapa pengelola kunci statis yang memiliki ThreadLocal<LockMode>
variabel anggota dan kemudian memiliki aspek yang membungkus setiap metode di setiap repositori yang disebut bindResource dengan mode kunci diatur di ThreadLocal. Ini akan memungkinkan Anda untuk mengatur mode kunci pada basis per-utas. Anda kemudian dapat membuat @MethodLockMode
Anda sendiri anotasi yang akan membungkus metode dalam aspek yang menyetel mode kunci khusus utas sebelum menjalankan metode dan menghapusnya setelah menjalankan metode.
Tautan Sumber Daya:
- Bagaimana cara mengaktifkan LockModeType.PESSIMISTIC_WRITE saat mencari entitas dengan Spring Data JPA?
- Cara menambahkan kustom metode untuk Spring Data JPA
- Spring Data Pessimistic Lock timeout dengan Postgres
- API Kueri JPA
Berbagai Contoh Batas Waktu Kunci Pesimistis
Menyetel Kunci Pesimis
Objek entitas dapat dikunci secara eksplisit dengan metode kunci:
em.lock(employee, LockModeType.PESSIMISTIC_WRITE);
Argumen pertama adalah objek entitas. Argumen kedua adalah mode kunci yang diminta.
TransactionRequiredException
dilempar jika tidak ada transaksi aktif saat penguncian dipanggil karena penguncian eksplisit memerlukan transaksi aktif.
Sebuah LockTimeoutException
dilemparkan jika kunci pesimistis yang diminta tidak dapat diberikan:
- Sebuah
PESSIMISTIC_READ
permintaan kunci gagal jika pengguna lain (yang diwakili oleh instance EntityManager lain) saat ini memegangPESSIMISTIC_WRITE
mengunci objek database tersebut. - Sebuah
PESSIMISTIC_WRITE
permintaan kunci gagal jika pengguna lain saat ini memegangPESSIMISTIC_WRITE
kunci atauPESSIMISTIC_READ
mengunci objek database itu.
Menyetel Petunjuk Kueri (Cakupan)
Petunjuk kueri dapat disetel dalam cakupan berikut (dari global ke lokal):
Untuk seluruh unit persistensi - menggunakan persistence.xml
properti:
<properties>
<property name="javax.persistence.query.timeout" value="3000"/>
</properties>
Untuk EntityManagerFactory - menggunakan createEntityManagerFacotory
metode:
Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 4000);
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("pu", properties);
Untuk EntityManager - menggunakan createEntityManager
metode:
Map<String,Object> properties = new HashMap();
properties.put("javax.persistence.query.timeout", 5000);
EntityManager em = emf.createEntityManager(properties);
atau menggunakan metode setProperty:
em.setProperty("javax.persistence.query.timeout", 6000);
Untuk named query
definisi - menggunakan hints
elemen:
@NamedQuery(name="Country.findAll", query="SELECT c FROM Country c",
hints={@QueryHint(name="javax.persistence.query.timeout", value="7000")})
Untuk eksekusi kueri tertentu - menggunakan setHint
metode (sebelum eksekusi kueri):
query.setHint("javax.persistence.query.timeout", 8000);