Neden bir sorgu önbelleğine ihtiyacınız var?

Çalışanları HQL'ye alarak örneğimizi yeniden yazalım:

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

assertTrue(director1 != director2);

Bu tür sorguların sonuçları, birinci veya ikinci düzey önbellekte saklanmaz .

Burası tam olarak sorgu önbelleğinin kullanılabileceği yerdir . Ayrıca varsayılan olarak devre dışıdır. Etkinleştirmek için yapılandırma dosyasına aşağıdaki satırı ekleyin:

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

Ancak bu, çözümün yalnızca yarısıdır. Sorgu önbelleğini etkinleştirdik, ancak hangi sorgu sonuçlarını önbelleğe almak istediğimizi de belirtmemiz gerekiyor. Bu, Sorguda yazılmalıdır:

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

Sorgu önbelleği, ikinci düzey önbelleğe benzer. Ancak, ondan farklı olarak, burada önbellek verilerinin anahtarı nesne tanımlayıcısı değil, sorgu parametreleri kümesidir. Ve verilerin kendisi, sorgu ölçütleriyle eşleşen nesnelerin tanımlayıcılarıdır. Bu nedenle, bu önbelleği ikinci seviye önbellek ile kullanmak mantıklıdır.

önbelleği temizleme

Bir önbellekle çalışırken önemli görevlerden biri, önbelleğe alınan nesnelerin değişmesini sağlamak ve bunları önbellekten kaldırmak (veya güncellemek) sağlamaktır. Hibernate bunu çok iyi yapıyor. Hatta bazen "anlaşılmaz herhangi bir durumda önbelleği temizle" kuralı tarafından yönlendirildiği görülüyor.

Diyelim ki kullanıcı verilerini HQL aracılığıyla güncellemek istiyorsunuz:

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

Hazırda Bekletme, veritabanında neyin değiştiğini tam olarak bilemez, ancak bir Çalışan nesnesini değiştirdiğinizi bilir. Bu nedenle, bu sorguyu yürüttükten sonra Hibernate, Çalışan türündeki tüm nesneleri önbelleğinden silecektir .

Ancak NativeQuery daha da ilginç çalışır:

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

Veritabanına yerel bir SQL sorgusu yürütüldü. Bu, veritabanında bir şeylerin değiştiği anlamına gelir - istek, executeUpdate() yönteminde çağrıldı . Bu nedenle, bu durumda, Hibernate güvenli bir şekilde oynayacak ve her türdeki tüm nesneleri önbelleğinden kaldıracaktır .

Bunu nasıl seversin? Zararsız bir istek çağırırsınız ve yanıt olarak Hazırda Beklet, önbellekten tüm verileri siler! Bu kesinlikle tabandan farklı nesneleri tutmasından daha iyidir, ama bu kadar!

Bu nedenle, Hibernate'in yaratıcıları, bu durumda Hibernate'e nasıl yardım edeceklerini çabucak anladılar. Önbellekten hangi varlık türünün kaldırılacağını söyleyebilirsiniz:

Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4");
nativeQuery.unwrap(org.hibernate.SQLQuery.class).addSynchronizedEntityClass(Employee.class);
nativeQuery.executeUpdate();
not . Yerel seçim sorguları önbelleği temizlemez , yalnızca ekleme, güncelleme, silme, prosedür çağrıları vb.

Manuel önbellek temizleme

Bazı nedenlerden dolayı önbellekten bir nesneyi kendiniz silmek isteyebilirsiniz. Bu farklı şekillerde yapılabilir.

not . Önbellekteki nesneler, bölge adı verilen gruplarda saklanır . Varsayılan olarak, bölge adı sınıf adıyla aynıdır. Bu nedenle, com.codegym.Employee türünde nesneleriniz varsa , hepsi " com.codegym.employee " adlı bir grupta (bölgede) saklanacaktır.

Önbelleğe erişmek ve onunla bir şeyler yapmak istiyorsanız, bunu SessionFactory nesnesi ve getCache () yöntemiyle yapabilirsiniz :

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

Tüm gruplardan (bölgelerden) veri silmek istiyorsanız, aşağıdaki sorguyu çalıştırmanız gerekir:

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

Bir nesneyi önbellekten kaldırmak için adını (türünü) ve kimliğini iletmeniz gerekir. Bunu iki şekilde yapabilirsiniz:

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

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

Belirli bir nesnenin önbellekte olup olmadığını da kontrol edebilirsiniz:

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