Tecnologie |
Dettaglio dell'articolo:
domenica 18 febbraio 2007
Una applicazione dovrebbe essere in grado di mantenere una cache
contenente i dati già caricati dal database, e consultare il
database solo quando i dati sono stati modificati.
Hibernate implementa due livelli di cache:
Figura 1. Hibernate senza nessuna Cache
Figura 2. Hibernate con una Cache
Una cache su singola jvm, come descritto sin qui, è una cache a livello di sessione. Se c'è la necessità di costruire un sistema che si basi su pi๠di una jvm, sarà necessario utilizzare una cache distribuita. Sfortunatamente non esiste una soluzione ideale al problema di una cache distribuita in collegamento con un sistema legacy.Se la tua applicazione che utilizza hibernate accede in modo read-only sul database, potrà essere possibile configurare delle cache che scadono periodicamente. Se sei in grado di controllare tutti gli accessi ad un particolare istanza del database, puoi usare una cache distribuita per assicurare che il traffico dei dati è propriamente sincronizzato. Un esempio di questo è mostrato in Figura 4. Fare attenzione che l'overhead del traffico dovuto alla sincronizzazione della cache non sia maggiore dei vantaggi dati dai dati tenuti in cache.
Configurazione di una cacheApplicazioni che effettuano un grande numero di letture in relazione al numero di operazioni di scrittura in genere traggono massimo beneficio dall'aggiunta di una cache. Il tipo di cache che si adatta meglio dipende da fattori come l'uso di JTA, requisiti di transaction isolation-level, ed utilizzo di cluster. A causa di queste ampie casistiche di utilizzo, Hibernate non implementa cache, ma si basa su librerie configurabili di terze parti. Tabella 1. Cache Supportate
Cache standard
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Cache |
Property Value |
|
EHCache |
net.sf.ehcache.hibernate.Provider (default) (Easy Hibernate Cache) |
|
OSCache (Open Symphony) |
net.sf.hibernate.cache.OSCacheProvider |
|
SwarmCache |
net.sf.hibernate.cache.Swarm CacheProvider |
|
JBoss TreeCache |
net.sf.hibernate.cache.TreeCache Provider |
|
Custom (User-Defined) |
Fully qualified class name pointing to a net.sf .hibernate.cache.CacheProvider implementation |
Indipendentemente da quale cache viene scelta, sarà necessario dire a Hibernate che tipo di regole per la cache devono essere applicate ai tuoi dati. Questo viene definito utilizzando il tag cache. Puoi impostare il tag cache nel tuo file *.hbm.xml o nel file hibernate.cfg.xml. E' anche possibile configurare le impostazioni della cache da programma utilizzando l'oggetto Configuration. La Tabella 3 mostra i valori consentiti per il tag cache.
|
Option |
Comment |
|
read-only |
Utile solo se l'applicazione accede in sola lettura ai dati (ma non effettua modifiche). Particolarmente utile se il cache provider supporta l'expiration automatica della cache.Deve essere anche impostato a mutable=false il tag per la parent class/collection. |
|
read-write |
Questa strategia mantiene lo stato della cache "read
committed", utilizzando un meccanismo di timestamping ed è
diponibile solo in ambienti non clustered. |
|
nonstrict-read-write |
Non verifica che due transazioni modifichino gli stessi
dati;
questo è lasciato all'applicazione. |
|
transactional |
Cache a transazioni distribuite. |
|
Cache |
read-only |
nonstrict-read-write |
read-write |
transactional |
|
EHCache |
Yes |
Yes |
Yes |
|
|
OSCache |
Yes |
Yes |
Yes |
|
|
SwarmCache |
Yes |
Yes |
|
|
|
JBoss TreeCache |
Yes |
|
|
Yes |
Query Cache
I risultati di una query possono essere salvati in cache. Per utilizzare la query cache, essa deve essere abilitata:
hibernate.cache.use_query_cache trueJava Transaction API (JTA)
Seguendo la documentazione Sun, JTA "definisce le interfacce
Java
standard tra un transaction manager e tutte le componenti coinvolte in
un
distributed transaction system: resource manager, application
server, e applicazioni transazionali." In altre parole, JTA riguarda le
transazioni che coinvolgono pi๠application server. Per
ulteriori dettagli consultare (http://java.sun.com/products/jta/).
Un esempio pratico
Supponiamo di dover
utilizzare quanto detto in una applicazione che utilizzi un oggetto
Category e degli oggetti Item, ovviamente associati alla propria
categoria. Tali oggetti Item sono inoltri associati a delle Bid, che
rappresentano offerte di acquisto relative all'oggetto. L'applicazione
utilizza inoltre la classe User per definire gli utenti.
Iniziamo ad aggiungere l'elemento di mappatura necessario per
dire
ad Hibernate come gestire istanze della classe Category.
<class name="Category" table="CATEGORY">
<cache usage="read-write"></cache>
<id ...>
</id>
</class>
Viene usata l'opzione "read-write" invece di
"nonstrict-read-write" perchè Category è una classe che
può essere condivisa tra molte transazioni concorrenti. (E'
chiaro che un isolation level "read committed" può andar bene)
Un "nonstrict-read-write" si baserebbe su cache expiration (timeout),
ma è preferibile che le modifiche alle categoria siano visibili
immediatamente.
Questa mappatura è sufficiente per dire a Hibernate di mette in cache tutti i valori della Category, ma non lo stato di entità o collections. Le collections hanno bisogno del loro tag <cache>.</cache>
<class name="auction.model.Category" table="CATEGORY">
<cache usage="read-write"/>
<id ...>
</id>
<set name="items">
<cache usage="read-write"></cache>
<key ...>
</key>
</set>
</class>
Se è necessario che le istanze degli Item siano messi in
cache,devi abilitare il caching della classe Item. Una startegia
"read-write" è specialmente appropriata.
Andiamo avanti nell'esempio e consideriamo una collezione di bid associate ad un certo Item. Una Bid è immutabile, ma la collezione delle bid è mutabile, e moduli concorrenti devono vedere ogni aggiunta e rimozione di un elemento senza ritardi:
<class name="Item" table="ITEM">
<cache usage="read-write"></cache>
<id ...>
</id>
<set name="bids">
<cache usage="read-write"></cache>
<key ...>
</key>
</set>
</class>
Alla classe Bid può essere applicata una strategia "read-only":
<class name="Bid" table="BID" mutable="false">
<cache usage="read-only"></cache>
<id ...>
</id>
</class>
User è un esempio di classe che può essere messa in
cache utilizzando la strategia "nonstrict-read-write",
ammesso che abbia senso il caching degli utenti.
| Archivio |
Calendario |
Ricerca |
Bookmark |
Collegamento |