Mengapa anda memerlukan cache pertanyaan

Mari kita tulis semula contoh kita dengan mendapatkan pekerja 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 pertanyaan sedemikian tidak disimpan oleh cache tahap pertama atau kedua.

Di sinilah cache pertanyaan boleh digunakan . Ia juga dilumpuhkan secara lalai. Untuk mendayakannya, tambahkan baris berikut pada fail konfigurasi:

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

Tetapi ini hanya separuh penyelesaian. Kami telah mendayakan cache pertanyaan, tetapi kami juga perlu menentukan hasil pertanyaan yang ingin kami cache. Ini mesti ditulis dalam Pertanyaan:

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

Cache pertanyaan adalah serupa dengan cache tahap kedua. Tetapi, tidak seperti itu, di sini kunci kepada data cache bukanlah pengecam objek, tetapi set parameter pertanyaan. Dan data itu sendiri ialah pengecam objek yang sepadan dengan kriteria pertanyaan. Oleh itu, adalah rasional untuk menggunakan cache ini dengan cache tahap kedua.

Membersihkan cache

Salah satu tugas penting apabila bekerja dengan cache ialah memastikan objek cache berubah dan mengalih keluarnya daripada cache (atau mengemas kininya). Hibernate melakukan ini dengan baik. Kadang-kadang nampaknya dia dipandu oleh peraturan "kosongkan cache dalam sebarang situasi yang tidak dapat difahami."

Katakan anda ingin mengemas kini data pengguna melalui HQL:

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

Hibernate tidak dapat mengetahui dengan tepat apa yang telah berubah dalam pangkalan data, tetapi ia mengetahui bahawa anda sedang menukar objek Pekerja. Oleh itu, selepas melaksanakan pertanyaan ini, Hibernate akan memadam semua objek jenis Pekerja daripada cachenya.

Tetapi NativeQuery berfungsi dengan lebih menarik:

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

Pertanyaan SQL asli kepada pangkalan data telah dilaksanakan. Ini bermakna sesuatu telah berubah dalam pangkalan data - permintaan itu dipanggil dalam kaedah executeUpdate() . Oleh itu, dalam kes ini, Hibernate akan memainkannya dengan selamat dan mengalih keluar semua objek semua jenis daripada cachenya .

Bagaimana anda suka itu? Anda memanggil permintaan yang tidak berbahaya, dan Hibernate sebagai tindak balas memadamkan semua data daripada cache! Ini sememangnya lebih baik daripada jika dia menyimpan objek yang berbeza dari pangkalan, tetapi itu sahaja!

Oleh itu, pencipta Hibernate dengan cepat mengetahui cara membantu Hibernate dalam kes ini. Anda boleh memberitahunya jenis entiti yang hendak dialih keluar daripada cache:

Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4");
nativeQuery.unwrap(org.hibernate.SQLQuery.class).addSynchronizedEntityClass(Employee.class);
nativeQuery.executeUpdate();
Teguran . Pertanyaan pilihan asli tidak membuang cache , hanya masukkan, kemas kini, padam, panggilan prosedur, dsb.

Pembersihan cache manual

Atas sebab tertentu, anda mungkin mahu memadamkan objek daripada cache sendiri. Ini boleh dilakukan dengan cara yang berbeza.

Nota . Objek dalam cache disimpan dalam kumpulan yang dipanggil wilayah . Secara lalai, nama rantau adalah sama dengan nama kelas. Oleh itu, jika anda mempunyai objek jenis com.codegym.Employee , maka kesemuanya akan disimpan dalam kumpulan (rantau) dengan nama “ com.codegym.employee ”.

Jika anda ingin mengakses cache dan melakukan sesuatu dengannya, anda boleh melakukannya dengan objek SessionFactory dan kaedah getCache() :

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

Jika anda ingin memadamkan data daripada semua kumpulan (wilayah), maka anda perlu menjalankan pertanyaan berikut:

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

Untuk mengalih keluar satu objek daripada cache, anda perlu menghantar namanya (jenis) dan id. Anda boleh melakukan ini dalam dua cara:

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

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

Anda juga boleh menyemak sama ada objek tertentu berada dalam cache:

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