Dlaczego potrzebujesz pamięci podręcznej zapytań

Przepiszmy nasz przykład z pozyskiwaniem pracowników w HQL:

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

assertTrue(director1 != director2);

Wyniki takich zapytań nie są przechowywane ani w pamięci podręcznej pierwszego, ani drugiego poziomu.

Właśnie w tym miejscu można użyć pamięci podręcznej zapytań . Jest również domyślnie wyłączone. Aby go włączyć, dodaj następujący wiersz do pliku konfiguracyjnego:

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

Ale to tylko połowa rozwiązania. Włączyliśmy pamięć podręczną zapytań, ale musimy również określić, które wyniki zapytań chcemy buforować. To musi być napisane w zapytaniu:

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

Pamięć podręczna zapytań jest podobna do pamięci podręcznej drugiego poziomu. Ale w przeciwieństwie do tego, tutaj kluczem do danych w pamięci podręcznej nie jest identyfikator obiektu, ale zestaw parametrów zapytania. A same dane to identyfikatory obiektów, które pasują do kryteriów zapytania. Dlatego racjonalne jest używanie tej pamięci podręcznej z pamięcią podręczną drugiego poziomu.

Czyszczenie pamięci podręcznej

Jednym z ważnych zadań podczas pracy z pamięcią podręczną jest upewnienie się, że obiekty w pamięci podręcznej zmieniają się i usuwają je z pamięci podręcznej (lub aktualizują). Hibernate robi to bardzo dobrze. Czasami wydaje się nawet, że kieruje się zasadą „wyczyść pamięć podręczną w każdej niezrozumiałej sytuacji”.

Załóżmy, że chcesz zaktualizować dane użytkownika za pośrednictwem HQL:

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

Hibernate nie może dokładnie wiedzieć, co się zmieniło w bazie danych, ale wie, że zmieniasz obiekt pracownika. Dlatego po wykonaniu tego zapytania Hibernate usunie wszystkie obiekty typu Employee ze swojej pamięci podręcznej.

Ale NativeQuery działa jeszcze bardziej interesująco:

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

Wykonano natywne zapytanie SQL do bazy danych. Oznacza to, że coś się zmieniło w bazie danych - żądanie zostało wywołane w metodzie executeUpdate() . Dlatego w tym przypadku Hibernate zagra bezpiecznie i usunie wszystkie obiekty wszystkich typów ze swojej pamięci podręcznej .

Jak ci się to podoba? Wywołujesz nieszkodliwe żądanie, a Hibernate w odpowiedzi usuwa wszystkie dane z pamięci podręcznej! Jest to z pewnością lepsze niż gdyby trzymał przedmioty różniące się od podstawy, ale to wszystko!

Dlatego twórcy Hibernate szybko wymyślili, jak pomóc Hibernate w tym przypadku. Możesz powiedzieć, który typ jednostki ma zostać usunięty z pamięci podręcznej:

Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4");
nativeQuery.unwrap(org.hibernate.SQLQuery.class).addSynchronizedEntityClass(Employee.class);
nativeQuery.executeUpdate();
Uwaga . Natywne zapytania wybierające nie opróżniają pamięci podręcznej , a jedynie wstawiają, aktualizują, usuwają, wywołują wywołania procedur itp.

Ręczne czyszczenie pamięci podręcznej

Z pewnych powodów możesz chcieć samodzielnie usunąć obiekt z pamięci podręcznej. Można to zrobić na różne sposoby.

Uwaga . Obiekty w pamięci podręcznej są przechowywane w grupach zwanych regionami . Domyślnie nazwa regionu jest taka sama jak nazwa klasy. Dlatego jeśli masz obiekty typu com.codegym.Employee , to wszystkie będą przechowywane w grupie (regionie) o nazwie „ com.codegym.employee ”.

Jeśli chcesz uzyskać dostęp do pamięci podręcznej i coś z nią zrobić, możesz to zrobić za pomocą obiektu SessionFactory i metody getCache() :

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

Jeśli chcesz usunąć dane ze wszystkich grup (regionów), musisz uruchomić następujące zapytanie:

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

Aby usunąć jeden obiekt z pamięci podręcznej, należy podać jego nazwę (typ) oraz id. Możesz to zrobić na dwa sposoby:

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

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

Możesz także sprawdzić, czy dany obiekt znajduje się w pamięci podręcznej:

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