2015-07-23 19 views
12

Sto utilizzando Spring Boot 1.2.5 con JPA2 per annotare le entità (e ibernare come underlaying di implementazione JPA).Spring Boot + JPA2 + Hibernate - abilita la cache di secondo livello

ho voluto usare la cache di secondo livello in quella di impostazione, quindi soggetti sono stati annotati con @javax.persistence.Cacheable

Ho anche aggiunto segue in application.properties:

spring.jpa.properties.hibernate.cache.use_second_level_cache=true 
spring.jpa.properties.hibernate.cache.use_query_cache=true 
spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory 

Durante l'avvio di ibernazione lamentato la mancanza di EhCacheRegionFactory così ho anche aggiunto che questo pom:

<dependency> 
    <groupId>org.hibernate</groupId> 
    <artifactId>hibernate-ehcache</artifactId> 
</dependency> 

Ma interroga ancora come entityManager.find(Clazz.class, pk) sono lanciare la query DB invece di utilizzare i dati memorizzati nella cache.

Qualche idea di cosa manca?

+1

Spero che tu abbia abilitato la gestione della cache, nella tua classe di configurazione usando '@ EnableCaching' o nel file xml usando' '. – Arpit

+0

Anche se è usato solo per Spring Caching - voglio usare JPA2 Caching (aggiorna domanda per indicare che sto usando '@ javax.persistence.Cacheable') a livello di classe – Daimon

risposta

19

Beh, dopo un po 'di scavo ecco cosa mi mancava in application.properties:

spring.jpa.properties.javax.persistence.sharedCache.mode=ALL 

Speranza che aiuta qualcuno :)

+0

Thx Daimon, e per chiunque arrivi così lontano, vale la pena notare che hai bisogno di entrambe le configurazioni dalla domanda, oltre alla configurazione di questa risposta. – Xiangyu

+6

È preferibile impostare 'spring.jpa.properties.javax.persistence.sharedCache.mode = ENABLE_SELECTIVE' perché solo allora onorerai le tue annotazioni' @ javax.persistence.Cacheable '. –

+0

Ho risolto il problema impostando questa proprietà: hibernate.cache.region.factory_class –

0

Si dovrebbe avere un file ehcache.xml nel classpath. Il file dovrebbe contenere almeno la strategia cache predefinita. Per facilitare debuging, rendono eterna per essere sicuri soggetti non sono sfrattati dalla cache:

ehcache.xml:

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:noNamespaceSchemaLocation="ehcache.xsd" 
    Name="CacheManager" 
    maxBytesLocalHeap="250m"> 

<defaultCache eternal="true" 
... 
/> 

<cache name="org.hibernate.cache.internal.StandardQueryCache" 
     eternal="true" 
... 
/> 

Per assicurarsi che tutto è ok, si dovrebbe avere il seguente registro durante il vostro avvio dell'applicazione:

Could not find a specific ehcache configuration for cache named [com.yourcompany.YourClass]; Using defaults. 

Ciò significa che l'annotazione della cache delle entità è stata correttamente letta e verrà utilizzata la cache predefinita.

Se si prova con entityManager.find(Clazz.class, pk) che non coinvolge la cache di query, ma solo la cache di entità. cache delle query viene utilizzato per le query (em.createQuery (...) e per la nave di relazioni

Inoltre, io uso org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory, ma non so wich è meglio.

+1

Mentre è consigliabile avere' ehcache.xml', non è assolutamente necessario. Ehcache userà la configurazione predefinita della cache che ti dà 10.000 elementi e un TTL di 120s - questo non è regolato, ma è un punto di partenza che è abbastanza buono per molti. Nota anche che avere il file 'ehcache.xml' non è sufficiente, devi anche definire le cache appropriate per sbarazzarti di tutti gli avvertimenti. –

6

@Daimon io non sono davvero sicuro, se

spring.jpa.properties.javax.persistence.sharedCache.mode=ALL 

è la migliore decisione.

Citato da Hibernate 20.2.1. Cache mappings documentation section

Per impostazione predefinita, le entità non fanno parte del secondo livello di cache e si consiglia di attenersi a questa impostazione. Tuttavia, è possibile sovrascriverlo impostando l'elemento shared-cache-mode nel file persistence.xml o utilizzando la proprietà javax.persistence.sharedCache.mode nella configurazione.

mentre

ENABLE_SELECTIVE (Default e valore consigliato): soggetti non sono memorizzati nella cache se non esplicitamente contrassegnato come cacheable.

Quindi, potrebbe essere, che non hai annotato tutte le entità interessate con @ javax.persistence.Cacheable o piuttosto @ org.hibernate.annotations.Cache? Ciò potrebbe influire sul fatto che la Query Cache ha tentato di cercare le entità interessate nella Second Level Cache senza successo e quindi ha iniziato a recuperare ciascuna entità con una singola selezione.

+0

No, non era il caso. spring.jpa.properties.javax.persistence.sharedCache.mode deve essere impostato in modo esplicito. Se è tutto o impostazioni diverse è un'altra storia e non è correlata a questo problema stesso – Daimon

+1

Per aggiungere i miei due cent: Con Spring Boot 1.4 e Ehcache e Hibernate 5.1 è necessario almeno impostare la regione factory e la modalità cache condivisa. Anche se "ENABLE_SELECTIVE" è documentato come predefinito, ho avuto bisogno di impostarlo esplicitamente su questo valore. –

0

Forse si aggiunge

@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY) 

sulla classe che si desidera memorizzare nella cache?

Problemi correlati