Perché hai bisogno di una cache delle query

Riscriviamo il nostro esempio con l'inserimento di dipendenti in HQL:

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

assertTrue(director1 != director2);

I risultati di tali query non vengono memorizzati né dalla cache di primo né da quella di secondo livello.

Questo è esattamente il punto in cui può essere utilizzata la cache delle query . Inoltre è disabilitato per impostazione predefinita. Per abilitarlo, aggiungi la seguente riga al file di configurazione:

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

Ma questa è solo metà della soluzione. Abbiamo abilitato la cache delle query, ma dobbiamo anche specificare quali risultati della query vogliamo memorizzare nella cache. Questo deve essere scritto nella Query:

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

La cache delle query è simile a una cache di secondo livello. Ma, diversamente, qui la chiave per i dati della cache non è l'identificatore dell'oggetto, ma l'insieme dei parametri della query. E i dati stessi sono gli identificatori degli oggetti che corrispondono ai criteri della query. Pertanto, è razionale utilizzare questa cache con la cache di secondo livello.

Svuotare la cache

Una delle attività importanti quando si lavora con una cache è assicurarsi che gli oggetti memorizzati nella cache cambino e rimuoverli dalla cache (o aggiornarli). Hibernate lo fa molto bene. A volte sembra addirittura che sia guidato dalla regola "svuota la cache in qualsiasi situazione incomprensibile".

Supponiamo che tu voglia aggiornare i dati utente tramite HQL:

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

Hibernate non può sapere esattamente cosa è cambiato nel database, ma sa che stai modificando un oggetto Employee. Pertanto, dopo aver eseguito questa query, Hibernate eliminerà tutti gli oggetti di tipo Employee dalla sua cache.

Ma NativeQuery funziona in modo ancora più interessante:

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

È stata eseguita una query SQL nativa al database. Ciò significa che qualcosa è cambiato nel database: la richiesta è stata chiamata nel metodo executeUpdate() . Pertanto, in questo caso, Hibernate giocherà sul sicuro e rimuoverà tutti gli oggetti di tutti i tipi dalla sua cache .

Come ti piace? Chiami una richiesta innocua e Hibernate in risposta cancella tutti i dati dalla cache! Questo è sicuramente meglio che se tenesse oggetti diversi dalla base, ma il gioco è fatto!

Pertanto, i creatori di Hibernate hanno capito rapidamente come aiutare Hibernate in questo caso. Puoi dirgli quale tipo di entità rimuovere dalla cache:

Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4");
nativeQuery.unwrap(org.hibernate.SQLQuery.class).addSynchronizedEntityClass(Employee.class);
nativeQuery.executeUpdate();
Osservazione . Le query di selezione native non svuotano la cache , solo inseriscono, aggiornano, eliminano, chiamate di procedura, ecc.

Cancellazione manuale della cache

Per alcuni motivi, potresti voler eliminare tu stesso un oggetto dalla cache. Questo può essere fatto in diversi modi.

Nota . Gli oggetti nella cache sono memorizzati in gruppi chiamati regioni . Per impostazione predefinita, il nome della regione è uguale al nome della classe. Pertanto, se disponi di oggetti di tipo com.codegym.Employee , tutti verranno archiviati in un gruppo (regione) con il nome " com.codegym.employee ".

Se vuoi accedere alla cache e fare qualcosa con essa, puoi farlo con l'oggetto SessionFactory e il metodo getCache() :

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

Se desideri eliminare i dati da tutti i gruppi (regioni), devi eseguire la seguente query:

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

Per rimuovere un oggetto dalla cache, devi passare il suo nome (tipo) e id. Puoi farlo in due modi:

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

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

Puoi anche controllare se un particolare oggetto è nella cache:

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