Pertama-tama saya akan membedakan antara kunci optimis dan pesimis, karena mereka berbeda dalam mekanisme dasarnya.
Penguncian optimis sepenuhnya dikendalikan oleh JPA dan hanya membutuhkan kolom versi tambahan di tabel DB. Ini sepenuhnya independen dari mesin DB dasar yang digunakan untuk menyimpan data relasional.
Di sisi lain, penguncian pesimis menggunakan mekanisme penguncian yang disediakan oleh basis data yang mendasarinya untuk mengunci catatan yang ada dalam tabel. JPA perlu mengetahui cara memicu penguncian ini dan beberapa database tidak mendukungnya atau hanya sebagian.
Sekarang ke daftar jenis kunci:
LockModeType.Optimistic
- Jika entitas menentukan bidang versi, ini adalah default. Untuk entitas tanpa kolom versi, menggunakan jenis kunci ini tidak dijamin akan berfungsi pada implementasi JPA apa pun. Mode ini biasanya diabaikan seperti yang dinyatakan oleh ObjectDB. Menurut pendapat saya itu hanya ada sehingga Anda dapat menghitung mode kunci secara dinamis dan meneruskannya lebih jauh bahkan jika kuncinya pada akhirnya OPTIMIS. Meskipun kasus penggunaan tidak terlalu mungkin, tetapi selalu merupakan desain API yang baik untuk memberikan opsi untuk referensi bahkan nilai default.
-
Contoh:
`LockModeType lockMode = resolveLockMode(); A a = em.find(A.class, 1, lockMode);`
LockModeType.OPTIMISTIC_FORCE_INCREMENT
- Ini adalah opsi yang jarang digunakan. Tapi bisa jadi masuk akal, jika Anda ingin mengunci referensi entitas ini oleh entitas lain. Dengan kata lain Anda ingin mengunci bekerja dengan suatu entitas meskipun tidak dimodifikasi, tetapi entitas lain dapat dimodifikasi sehubungan dengan entitas ini.
- Contoh:Kami memiliki entitas Buku dan Rak. Dimungkinkan untuk menambahkan Buku ke Rak, tetapi buku tidak memiliki referensi ke raknya. Tindakan memindahkan buku ke rak adalah wajar untuk mengunci, agar buku tidak berakhir di rak lain (karena transaksi lain) sebelum akhir transaksi ini. Untuk mengunci tindakan ini, tidak cukup mengunci entitas rak buku saat ini, karena buku belum harus berada di rak. Juga tidak masuk akal untuk mengunci semua rak buku target, karena mereka mungkin akan berbeda dalam transaksi yang berbeda. Satu-satunya hal yang masuk akal adalah mengunci entitas buku itu sendiri, meskipun dalam kasus kami entitas tersebut tidak berubah (tidak mengacu pada rak bukunya).
LockModeType.PESSIMISTIC_READ
- mode ini mirip dengan
LockModeType.PESSIMISTIC_WRITE
, tetapi berbeda dalam satu hal:sampai kunci tulis ditempatkan pada entitas yang sama oleh beberapa transaksi, itu tidak boleh memblokir pembacaan entitas. Ini juga memungkinkan transaksi lain untuk mengunci menggunakanLockModeType.PESSIMISTIC_READ
. Perbedaan antara MENULIS dan BACA kunci dijelaskan dengan baik di sini (ObjectDB) dan di sini (OpenJPA). Jika suatu entitas sudah dikunci oleh transaksi lain, setiap upaya untuk menguncinya akan menimbulkan pengecualian. Perilaku ini dapat dimodifikasi untuk menunggu beberapa saat hingga kunci dilepaskan sebelum melempar pengecualian dan memutar kembali transaksi. Untuk melakukannya, tentukanjavax.persistence.lock.timeout
petunjuk dengan jumlah milidetik untuk menunggu sebelum melempar pengecualian. Ada beberapa cara untuk melakukan ini di berbagai level, seperti yang dijelaskan dalam tutorial Java EE.
LockModeType.PESSIMISTIC_WRITE
- ini adalah versi yang lebih kuat dari
LockModeType.PESSIMISTIC_READ
. KetikaWRITE
kunci di tempat, JPA dengan bantuan database akan mencegah transaksi lain untuk membaca entitas, tidak hanya untuk menulis seperti denganREAD
kunci. - Cara bagaimana ini diterapkan di penyedia JPA yang bekerja sama dengan DB yang mendasarinya tidak ditentukan. Dalam kasus Anda dengan Oracle, saya akan mengatakan bahwa Oracle tidak menyediakan sesuatu yang dekat dengan
READ
kunci.SELECT...FOR UPDATE
sebenarnya adalahWRITE
kunci. Ini mungkin bug dalam hibernasi atau hanya keputusan bahwa, alih-alih menerapkanREAD
kustom "lebih lembut" kunci,WRITE
yang "lebih sulit" kunci digunakan sebagai gantinya. Ini sebagian besar tidak merusak konsistensi, tetapi tidak memegang semua aturan denganREAD
kunci. Anda dapat menjalankan beberapa tes sederhana denganREAD
kunci dan transaksi yang berjalan lama untuk mengetahui apakah lebih banyak transaksi dapat memperolehREAD
mengunci pada entitas yang sama. Ini harus dimungkinkan, sedangkan tidak denganWRITE
kunci.
- LockModeType.PESSIMISTIC_FORCE_INCREMENT
- ini adalah mode kunci lain yang jarang digunakan. Namun, ini adalah opsi di mana Anda perlu menggabungkan
PESSIMISTIC
danOPTIMISTIC
mekanisme. MenggunakanPESSIMISTIC_WRITE
biasa akan gagal dalam skenario berikut:- transaksi A menggunakan penguncian optimis dan membaca entitas E
- transaksi B memperoleh kunci WRITE pada entitas E
- transaksi B melakukan dan melepaskan kunci E
- transaksi A memperbarui E dan melakukan
- pada langkah 4, jika kolom versi tidak bertambah oleh transaksi B, tidak ada yang mencegah A untuk menimpa perubahan B. Mode kunci
LockModeType.PESSIMISTIC_FORCE_INCREMENT
akan memaksa transaksi B untuk memperbarui nomor versi dan menyebabkan transaksi A gagal denganOptimisticLockException
, meskipun B menggunakan penguncian pesimis.
- LockModeType.NONE
- ini adalah default jika entitas tidak menyediakan bidang versi. Ini berarti bahwa tidak ada penguncian yang diaktifkan, konflik akan diselesaikan dengan upaya terbaik dan tidak akan terdeteksi. Ini adalah satu-satunya mode penguncian yang diizinkan di luar transaksi