Strategie di concorrenza

Dopo aver abilitato la memorizzazione nella cache di secondo livello in Hibernate, è necessario spiegare a Hibernate quali oggetti Entity vogliamo memorizzare nella cache e come.

Per fare ciò, Hibernate ha un'annotazione speciale per le classi Entity - @Cache . Esempio:

@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)

Questa annotazione deve essere scritta per ogni entità Entity per la quale vogliamo utilizzare la cache di secondo livello. Esempio:

@Entity
@Table(name = "employee")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Employee {
    @Id
    private Integer id;
    private Set<Task> tasks;
}

Hibernate ha 4 possibili strategie di accesso per un'entità memorizzata nella cache se vi si accede da thread diversi:

  • sola lettura
  • leggere scrivere
  • nonstrict-lettura-scrittura
  • transazionale

Sola lettura . Una strategia di concorrenza appropriata ai dati che non cambia mai. Hibernate memorizzerà semplicemente questi oggetti nella sua memoria. Usalo solo per i dati di riferimento.

I database memorizzano molte informazioni che non cambiano mai. Ad esempio, una tabella mantiene un elenco di eventi che vengono solo aggiunti ma mai modificati o rimossi. Se hai bisogno di lavorare con questa tabella tramite Hibernate, la strategia di memorizzazione nella cache di sola lettura ti si addice.

Lettura-scrittura (lettura-scrittura). Utilizzare questa strategia per i dati principalmente leggibili. Tuttavia, Hibernate terrà traccia dei tentativi di modificare questi dati, sebbene si aspetti che siano molto rari.

È necessario memorizzare nella cache principalmente quegli oggetti che cambiano raramente e vengono spesso letti/richiesti. Se disponi di tali oggetti, devi utilizzare la strategia di lettura-scrittura per essi.

Nonstrict-lettura-scrittura . Questa strategia non garantisce la coerenza tra la cache e il database. Utilizzare questa strategia se i dati non cambiano quasi mai e una piccola possibilità di dati obsoleti non è un problema critico.

A differenza della strategia di lettura-scrittura, questa strategia presuppone che i dati modificabili non siano bloccati per la lettura. Ciò può comportare la modifica dell'oggetto in un punto, mentre in un altro qualcuno ne sta leggendo la vecchia versione.

Ad esempio, un utente ha cambiato il suo commento, ma altri utenti continuano a vedere la sua vecchia versione per un po' di tempo. Se questo non è un problema per te, usa la strategia di lettura-scrittura non rigorosa.

Transazionale . Utilizzare questa strategia principalmente per i dati di sola lettura in cui è importante evitare dati obsoleti nelle transazioni simultanee nella rara occasione di un aggiornamento.

Archiviazione dei dati in una cache

Un altro dettaglio importante sulla cache di secondo livello che dovresti ricordare è che Hibernate non memorizza gli oggetti delle tue classi stesse. Memorizza le informazioni come array di stringhe, numeri, ecc.

E l'identificatore di oggetto funge da puntatore a queste informazioni. Concettualmente, questo è qualcosa di simile a una mappa, in cui l'id dell'oggetto è la chiave e gli array di dati sono il valore. Puoi immaginarlo così:

1 -> { "Ivanov", 1, null , {1,2,5} }
2 -> { "Petrov", 2, null , {1,2,5} }
3 -> { "Sidorov", 3, null , {1,2,5} }

Il che è molto ragionevole considerando quanta memoria extra occupa ogni oggetto.

Oltre a quanto sopra, dovresti ricordare che anche le dipendenze della tua classe Entity non vengono memorizzate nella cache per impostazione predefinita. Ad esempio, se consideriamo la classe precedente, Employee , durante il recupero, la raccolta delle attività verrà recuperata dal database e non dalla cache di secondo livello .

Se vuoi memorizzare nella cache anche le dipendenze, la classe dovrebbe apparire così:

@Entity
@Table(name = "employee")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Employee {
    @Id
    private Integer id;

   @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
   private Set<Task> tasks;
}

E l'ultimo dettaglio: la lettura dalla cache di secondo livello avviene solo se l'oggetto desiderato non è stato trovato nella cache di primo livello.

Modalità cache

Hibernate consente una gestione della cache molto flessibile. Puoi impostare la modalità cache per ogni singola sessione o anche per ogni richiesta di database.

Esistono cinque di queste modalità:

  • OTTENERE
  • IGNORARE
  • NORMALE
  • METTERE
  • RICARICARE

La tabella seguente descrive il loro lavoro:

Modalità cache Descrizione
OTTENERE I dati vengono letti dalla cache ma non aggiunti ad essa.
IGNORARE La sessione non interagisce con la cache.
NORMALE I dati vengono letti dalla cache e aggiunti ad essa.
METTERE I dati non vengono mai prelevati dalla cache, ma aggiunti ad essa.
RICARICARE I dati non vengono mai prelevati dalla cache, ma aggiunti ad essa. In questa modalità, viene utilizzata anche l'impostazione hibernate.cache.use_minimal_puts.

Un esempio di impostazione della modalità cache per una sessione:

session.setCacheMode(CacheMode.GET);
Employee director = session.createQuery("from Employee where id = 4").uniqueResult();

E anche un esempio di impostazione della modalità per la sessione e la richiesta:

session.setCacheMode(CacheMode.GET);
Query query = session.createQuery("from Employee where id = 4");
query.setCacheMode(CacheMode.IGNORE); // Ignore cache work for this request
Employee director = query.uniqueResult();