Mengapa Anda memerlukan cache kueri

Mari tulis ulang contoh kita dengan mendapatkan karyawan di HQL:

Employee director1 = session.createQuery("from Employee where id = 4").uniqueResult();
Employee director2 = session.createQuery("from Employee where id = 4").uniqueResult();

assertTrue(director1 != director2);

Hasil kueri tersebut tidak disimpan oleh cache tingkat pertama atau kedua.

Di sinilah cache kueri dapat digunakan . Ini juga dinonaktifkan secara default. Untuk mengaktifkannya, tambahkan baris berikut ke file konfigurasi:

<property name="hibernate.cache.use_query_cache" value="true"/>

Tapi ini hanya setengah dari solusi. Kami telah mengaktifkan cache kueri, tetapi kami juga perlu menentukan hasil kueri mana yang ingin kami cache. Ini harus ditulis dalam Query:

Query query = session.createQuery("from Employee where id = 4");
query.setCacheable(true);
Employee director1 = query.uniqueResult();

Cache kueri mirip dengan cache tingkat kedua. Namun, tidak seperti itu, di sini kunci untuk data cache bukanlah pengidentifikasi objek, tetapi kumpulan parameter kueri. Dan data itu sendiri adalah pengidentifikasi objek yang cocok dengan kriteria kueri. Jadi, penggunaan cache ini dengan cache tingkat kedua adalah rasional.

Membersihkan cache

Salah satu tugas penting saat bekerja dengan cache adalah memastikan bahwa objek yang di-cache berubah dan menghapusnya dari cache (atau memperbaruinya). Hibernasi melakukan ini dengan sangat baik. Kadang-kadang bahkan tampaknya dia dipandu oleh aturan "hapus cache dalam situasi yang tidak dapat dipahami".

Katakanlah Anda ingin memperbarui data pengguna melalui HQL:

Query query = session.createQuery("update Employee set name=’Alex’ where id = 4")
query. executeUpdate();

Hibernasi tidak dapat mengetahui dengan pasti apa yang telah berubah dalam database, tetapi ia mengetahui bahwa Anda sedang mengubah objek Karyawan. Oleh karena itu, setelah menjalankan kueri ini, Hibernasi akan menghapus semua objek bertipe Karyawan dari cache-nya.

Tapi NativeQuery bekerja lebih menarik:

Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4")
nativeQuery.executeUpdate();

Kueri SQL asli ke database telah dijalankan. Ini berarti ada sesuatu yang berubah dalam database - permintaan dipanggil dalam metode executionUpdate() . Oleh karena itu, dalam hal ini, Hibernate akan memainkannya dengan aman dan menghapus semua objek dari semua jenis dari cache-nya .

bagaimana kamu suka itu? Anda memanggil permintaan yang tidak berbahaya, dan Hibernasi sebagai tanggapan akan menghapus semua data dari cache! Ini tentu lebih baik daripada jika dia menyimpan benda yang berbeda dari dasarnya, tapi itu saja!

Oleh karena itu, pembuat Hibernasi dengan cepat menemukan cara membantu Hibernasi dalam kasus ini. Anda dapat menentukan jenis entitas mana yang akan dihapus dari cache:

Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4");
nativeQuery.unwrap(org.hibernate.SQLQuery.class).addSynchronizedEntityClass(Employee.class);
nativeQuery.executeUpdate();
Catatan . Kueri pemilihan asli tidak mengosongkan cache , hanya menyisipkan, memperbarui, menghapus, panggilan prosedur, dll.

Pembersihan cache secara manual

Untuk alasan tertentu, Anda mungkin ingin menghapus sendiri objek dari cache. Ini dapat dilakukan dengan berbagai cara.

Catatan . Objek dalam cache disimpan dalam grup yang disebut wilayah . Secara default, nama wilayah sama dengan nama kelas. Oleh karena itu, jika Anda memiliki objek bertipe com.codegym.Employee , maka semuanya akan disimpan dalam grup (region) dengan nama “ com.codegym.employee ”.

Jika Anda ingin mengakses cache dan melakukan sesuatu dengannya, Anda dapat melakukannya dengan objek SessionFactory dan metode getCache() :

session.getSessionFactory().getCache().evictQueryRegion("com.codegym.employee”);

Jika Anda ingin menghapus data dari semua grup (wilayah), maka Anda perlu menjalankan kueri berikut:

session.getSessionFactory().getCache().evictAllRegions();

Untuk menghapus satu objek dari cache, Anda harus memberikan nama (tipe) dan idnya. Anda dapat melakukannya dengan dua cara:

session.getSessionFactory().getCache().evictEntityData("Employee, 4);

session.getSessionFactory().getCache().evictEntityData(com.codegym.Employee.class, 4);

Anda juga dapat memeriksa apakah objek tertentu ada di dalam cache:

session.getSessionFactory().getCache().containsEntity("Employee, 4);
session.getSessionFactory().getCache().containsEntity(com.codegym.Employee.class, 4);