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);