Miért van szüksége lekérdezési gyorsítótárra?
Írjuk át a példánkat az alkalmazottak HQL-be vonásával:
Employee director1 = session.createQuery("from Employee where id = 4").uniqueResult();
Employee director2 = session.createQuery("from Employee where id = 4").uniqueResult();
assertTrue(director1 != director2);
Az ilyen lekérdezések eredményeit sem az első, sem a második szintű gyorsítótár nem tárolja .
A lekérdezés gyorsítótár pontosan itt használható . Alapértelmezés szerint szintén le van tiltva. Az engedélyezéséhez adja hozzá a következő sort a konfigurációs fájlhoz:
<property name="hibernate.cache.use_query_cache" value="true"/>
De ez csak a megoldás fele. Engedélyeztük a lekérdezés gyorsítótárat, de meg kell adnunk azt is, hogy mely lekérdezések eredményeit szeretnénk gyorsítótárba helyezni. Ezt be kell írni a lekérdezésbe:
Query query = session.createQuery("from Employee where id = 4");
query.setCacheable(true);
Employee director1 = query.uniqueResult();
A lekérdezési gyorsítótár hasonló a második szintű gyorsítótárhoz. De ezzel ellentétben itt a gyorsítótár adatok kulcsa nem az objektumazonosító, hanem a lekérdezési paraméterek halmaza. Maguk az adatok pedig a lekérdezési feltételeknek megfelelő objektumok azonosítói. Így ésszerű ezt a gyorsítótárat a második szintű gyorsítótárral együtt használni.
A gyorsítótár törlése
A gyorsítótárral végzett munka során az egyik fontos feladat annak biztosítása, hogy a gyorsítótárban lévő objektumok megváltozzanak, és eltávolítsák őket a gyorsítótárból (vagy frissítsék). A Hibernate ezt nagyon jól csinálja. Néha még úgy tűnik, hogy a szabály vezérli: „Tisztítsa meg a gyorsítótárat bármilyen érthetetlen helyzetben”.
Tegyük fel, hogy frissíteni szeretné a felhasználói adatokat HQL-n keresztül:
Query query = session.createQuery("update Employee set name=’Alex’ where id = 4")
query. executeUpdate();
A Hibernate nem tudja pontosan, hogy mi változott az adatbázisban, de tudja, hogy Ön egy Employee objektumot módosít. Ezért a lekérdezés végrehajtása után a Hibernate törli az összes Employee típusú objektumot a gyorsítótárából.
De a NativeQuery még érdekesebben működik:
Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4")
nativeQuery.executeUpdate();
Egy natív SQL-lekérdezés az adatbázishoz végrehajtva. Ez azt jelenti, hogy valami megváltozott az adatbázisban – a kérést az executeUpdate() metódus hívta meg . Ezért ebben az esetben a Hibernate biztonságosan lejátssza, és minden típusú objektumot eltávolít a gyorsítótárából .
Hogy tetszik? Ártalmatlan kérést hív, és válaszul a hibernált állapot törli az összes adatot a gyorsítótárból! Ez minden bizonnyal jobb, mintha az alaptól eltérő tárgyakat tartana, de ez van!
Ezért a Hibernate készítői gyorsan kitalálták, hogyan segíthetnek ebben az esetben a Hibernate-nak. Megadhatja, hogy melyik entitástípust távolítsa el a gyorsítótárból:
Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4");
nativeQuery.unwrap(org.hibernate.SQLQuery.class).addSynchronizedEntityClass(Employee.class);
nativeQuery.executeUpdate();
Megjegyzés . A natív kiválasztási lekérdezések nem ürítik ki a gyorsítótárat , csak beszúrnak, frissítenek, törölnek, eljáráshívásokat stb.
Kézi gyorsítótár törlése
Bizonyos okok miatt érdemes lehet saját maga törölni egy objektumot a gyorsítótárból. Ezt különböző módon lehet megtenni.
Megjegyzés . A gyorsítótárban lévő objektumok régióknak nevezett csoportokban tárolódnak . Alapértelmezés szerint a régió neve megegyezik az osztálynévvel. Ezért ha com.codegym.Employee típusú objektumai vannak , akkor mindegyik egy csoportban (régióban) lesz tárolva „ com.codegym.employee ” néven.
Ha hozzá szeretne férni a gyorsítótárhoz, és tenni szeretne vele valamit, akkor ezt megteheti a SessionFactory objektummal és a getCache() metódussal :
session.getSessionFactory().getCache().evictQueryRegion("com.codegym.employee”);
Ha az összes csoportból (régióból) szeretne adatokat törölni, akkor a következő lekérdezést kell futtatnia:
session.getSessionFactory().getCache().evictAllRegions();
Egy objektum gyorsítótárból való eltávolításához át kell adnia annak nevét (típusát) és azonosítóját. Ezt kétféleképpen teheti meg:
session.getSessionFactory().getCache().evictEntityData("Employee”, 4);
session.getSessionFactory().getCache().evictEntityData(com.codegym.Employee.class, 4);
Azt is ellenőrizheti, hogy egy adott objektum van-e a gyorsítótárban:
session.getSessionFactory().getCache().containsEntity("Employee”, 4);
session.getSessionFactory().getCache().containsEntity(com.codegym.Employee.class, 4);