Saya sarankan menambahkan @Startup
@Singleton
class yang membuat koneksi JDBC ke database PostgreSQL dan menggunakan LISTEN
dan NOTIFY
untuk menangani pembatalan cache.
Perbarui :Inilah pendekatan lain yang menarik, menggunakan pgq dan kumpulan pekerja untuk pembatalan.
Pembatalan sinyal
Tambahkan pemicu pada tabel yang sedang diperbarui yang mengirimkan NOTIFY
setiap kali entitas diperbarui. Pada PostgreSQL 9.0 dan di atasnya NOTIFY
dapat berisi muatan, biasanya ID baris, jadi Anda tidak perlu membatalkan seluruh cache, hanya entitas yang telah berubah. Pada versi yang lebih lama di mana payload tidak didukung, Anda dapat menambahkan entri yang tidak valid ke tabel log stempel waktu yang ditanyakan oleh kelas pembantu Anda saat mendapat NOTIFY
, atau batalkan saja seluruh cache.
Kelas pembantu Anda sekarang LISTEN
s pada NOTIFY
peristiwa yang dikirim oleh pemicu. Ketika mendapat NOTIFY
peristiwa, itu dapat membatalkan entri cache individu (lihat di bawah), atau menyiram seluruh cache. Anda dapat mendengarkan notifikasi dari database dengan dukungan mendengarkan/memberitahu PgJDBC. Anda harus membuka bungkus koneksi yang dikelola java.sql.Connection
untuk mendapatkan implementasi PostgreSQL yang mendasarinya sehingga Anda dapat mentransmisikannya ke org.postgresql.PGConnection
dan panggil getNotifications()
di atasnya.
Sebuah alternatif untuk LISTEN
dan NOTIFY
, Anda dapat melakukan polling pada tabel log perubahan pada pengatur waktu, dan memiliki pemicu pada tabel masalah untuk menambahkan ID baris yang diubah dan mengubah stempel waktu ke tabel log perubahan. Pendekatan ini akan portabel kecuali untuk kebutuhan pemicu yang berbeda untuk setiap jenis DB, tetapi tidak efisien dan kurang tepat waktu. Ini akan membutuhkan polling yang sering tidak efisien, dan masih memiliki waktu tunda yang tidak dimiliki oleh pendekatan mendengarkan/memberitahu. Di PostgreSQL Anda dapat menggunakan UNLOGGED
tabel untuk mengurangi biaya pendekatan ini sedikit.
Tingkat cache
EclipseLink/JPA memiliki beberapa level caching.
Cache level 1 ada di EntityManager
tingkat. Jika entitas dilampirkan ke EntityManager
oleh persist(...)
, merge(...)
, find(...)
, dll, lalu EntityManager
diperlukan untuk mengembalikan contoh yang sama dari entitas tersebut ketika diakses lagi dalam sesi yang sama, apakah aplikasi Anda masih memiliki referensi ke sana atau tidak. Instance terlampir ini tidak akan diperbarui jika konten database Anda telah berubah.
Cache level 2, yang opsional, ada di EntityManagerFactory
level dan merupakan cache yang lebih tradisional. Tidak jelas apakah Anda mengaktifkan cache level 2 atau tidak. Periksa log EclipseLink Anda dan persistence.xml
. Anda . Anda bisa mendapatkan akses ke cache level 2 dengan EntityManagerFactory.getCache()
; lihat Cache
.
@thedayofcondor menunjukkan cara membersihkan cache level 2 dengan:
em.getEntityManagerFactory().getCache().evictAll();
tetapi Anda juga dapat mengeluarkan objek individual dengan evict(java.lang.Class cls, java.lang.Object primaryKey)
hubungi:
em.getEntityManagerFactory().getCache().evict(theClass, thePrimaryKey);
yang dapat Anda gunakan dari @Startup
Anda @Singleton
NOTIFY
pendengar untuk membatalkan hanya entri yang telah diubah.
Cache level 1 tidak begitu mudah, karena ini adalah bagian dari logika aplikasi Anda. Anda ingin mempelajari tentang bagaimana EntityManager
, entitas terlampir dan terlepas, dll bekerja. Salah satu opsi adalah selalu menggunakan entitas terpisah untuk tabel yang dimaksud, di mana Anda menggunakan EntityManager
baru setiap kali Anda mengambil entitas. Pertanyaan ini:
Membatalkan sesi JPA EntityManager
memiliki diskusi yang berguna tentang penanganan pembatalan cache manajer entitas. Namun, sepertinya EntityManager
cache adalah masalah Anda, karena layanan web RESTful biasanya diimplementasikan menggunakan EntityManager
singkat sesi. Ini mungkin hanya menjadi masalah jika Anda menggunakan konteks persistensi yang diperluas, atau jika Anda membuat dan mengelola EntityManager
Anda sendiri sesi daripada menggunakan ketekunan yang dikelola penampung.