2011-06-08 20 views
8

Il titolo lo afferma chiaramente: non riesco a far funzionare la cache di secondo livello per JPA2/Hibernate 3.6.3.Esempio di funzionamento di Hibernate 3.6.2 Caching di secondo livello con JPA2?

Ho provato molti tentativi per farlo funzionare. Ma sto solo riuscendo a far funzionare la cache delle query. Sebbene Hibernate crei le cache (nome dell'istanza), vengono ignorate. Persino i miss non sono registrati. Forse è una incompatibilità di versione. Ho provato alcuni altri senza risultato. E non mi sento più all'altezza di provare tutte le permutazioni. :-P

Sto ponendo la domanda qui come alcune persone sembrano averlo funzionante (i cui esempi ho provato anche). Forse riescono a individuare l'errore evidente che sto facendo.

Grazie in anticipo per qualcuno che mi aiuta! :-)

persistence.xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" 
     version="2.0"> 

<persistence-unit name="foo" transaction-type="RESOURCE_LOCAL"> 
    <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode> 
    <properties> 
     <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver"/> 
     <property name="javax.persistence.jdbc.url" value="jdbc:derby:/opt/db/foo;create=true"/> 
     <property name="javax.persistence.jdbc.user" value="foo"/> 
     <property name="javax.persistence.jdbc.password" value="bar"/> 
     <property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect"/> 
     <property name="hibernate.hbm2ddl.auto" value="create"/> 
     <property name="hibernate.cache.region.factory_class" value="net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory"/> 
     <property name="hibernate.cache.use_second_level_cache" value="true"/> 
     <property name="hibernate.cache.use_query_cache" value="true"/> 
    </properties> 
</persistence-unit> 

pom.xml

configurazione
<dependency> 
     <groupId>org.hibernate</groupId> 
     <artifactId>hibernate-entitymanager</artifactId> 
     <version>3.6.3.Final</version> 
    </dependency> 
    <dependency> 
     <groupId>org.hibernate.javax.persistence</groupId> 
     <artifactId>hibernate-jpa-2.0-api</artifactId> 
     <version>1.0.0.Final</version> 
    </dependency> 
    <dependency> 
     <groupId>net.sf.ehcache</groupId> 
     <artifactId>ehcache-core</artifactId> 
    <version>2.4.2</version> 

JMX

In questo modo posso controllare l'utilizzo delle cache. Le cache vengono create (una per ogni entità) e ci sono anche le due cache di query. Questi ultimi si stanno riempiendo abbastanza velocemente. Ma nessuna delle cache mostra errori o colpi. Nemmeno le cache delle query.

ManagementService.registerMBeans(CacheManager.getInstance(), ManagementFactory.getPlatformMBeanServer(), true, true, true, true, true) 

Le cache di entità vengono ignorate. Dovrebbero contenere almeno le entità che vengono salvate nel database. O essere recuperato con le domande. Niente si muove lì.

Esempio di codice Java

EntityManager entityManager = Persistence.createEntityManagerFactory("foo").createEntityManager(); 
entityManager.getTransaction.begin(); 
entityManager.merge(bar); 
entityManager.getTransaction.commit(); 

Query query = entityManager.createQuery("select b from Bar p where b.name = :name"); 
query.setParameter("name", "fooBar"); 
query.setHint("org.hibernate.cacheable","true"); 
query.getSingleResult(); 

La fusione funziona - perché c'è dati nel database. E la ricerca funziona perché sto ricevendo oggetti con ID generati.

Le entità interrogate sono indicizzate nel database.

WHODUNNIT?

+1

Hai effettivamente contrassegnato le tue entità come @Cacheable? –

+0

Sì. E il pop-up di Windows giusto in JMX. Solo le entità non vengono memorizzate nella cache quando vengono interrogate. Non quando si persiste/si fondono. –

risposta

4

Trovato il colpevole - anche se è abbastanza intuitivo:

soggetti interrogati non sono messi nella cache di secondo livello a meno che non si chiude il gestore di sessione/entità. Anche se si esegue la query con gli stessi oggetti, non si verificherà alcuna memorizzazione nella cache.

Ho un processo batch lungo in cui vengono creati e riutilizzati molti oggetti di riferimento. Se tengo sempre lo stesso gestore di entità, non vedo la fine del processo. Se ricreo l'entity manager ad ogni ciclo, l'applicazione vola.

Ho pensato che esistesse qualcosa come una cache di primo livello: il contesto di persistenza?

4

Uno dei miei progetti utilizza ehcache + hibernate + jpa2. Ti dico la mia configurazione Spero che ti aiuti.

versioni quadro (esperto di dipendenza):

<dependency> 
    <groupId>org.hibernate</groupId> 
    <artifactId>hibernate-core</artifactId> 
    <!-- <version>3.6.2.Final</version> --> 
    <version>4.0.0.Alpha1</version> 
</dependency> 
<dependency> 
    <groupId>org.hibernate</groupId> 
    <artifactId>hibernate-entitymanager</artifactId> 
    <!-- <version>3.6.2.Final</version> --> 
    <version>4.0.0.Alpha1</version> 
</dependency> 
<dependency> 
    <groupId>org.eclipse.persistence</groupId> 
    <artifactId>javax.persistence</artifactId> 
    <version>2.0.0</version> 
</dependency> 
    <dependency> 
     <groupId>net.sf.ehcache</groupId> 
     <artifactId>ehcache-core</artifactId> 
     <version>2.3.1</version> 
    </dependency> 

Le due versioni Hibernate sono testati, ma non utilizzare l'API di ibernazione jpa2.

persistence.xml:

<persistence-unit name="UNIT" transaction-type="RESOURCE_LOCAL"> 
    <provider>org.hibernate.ejb.HibernatePersistence</provider> 
    <non-jta-data-source>java:/comp/env/ds</non-jta-data-source> 
    <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode> 
    <properties> 
     <property name="hibernate.show_sql" value="true" /> 
     <property name="hibernate.format_sql" value="false" /> 
     <property name="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect"/> 

     <!-- 2nd level cache --> 
     <property name="hibernate.cache.provider_class" 
      value="net.sf.ehcache.hibernate.SingletonEhCacheProvider"/> 
     <property name="net.sf.ehcache.configurationResourceName" 
      value="/ehcache.xml" /> 
     <property name="hibernate.cache.use_query_cache" value="true" /> 
     <property name="hibernate.cache.use_second_level_cache" 
      value="true" /> 
     <property name="hibernate.generate_statistics" value="false" /> 
    </properties> 
</persistence-unit> 

EHCache.xml:

<ehcache updateCheck="false"> 

    <diskStore path="java.io.tmpdir" /> 

    <defaultCache maxElementsInMemory="10000" eternal="false" 
     statistics="true" timeToIdleSeconds="120" timeToLiveSeconds="120" 
     overflowToDisk="true" diskPersistent="false" 
     diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" /> 

    <cache name="com.yourcompany.CachedEntity" eternal="true" 
     maxElementsInMemory="1000" />      
</ehcache> 

Infine si dovrebbe annotare il cachable classe di entità. Ecco un esempio:

package com.yourcompany; 
@Entity 
@Table(name="cached_entity") 
@Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 
public class CachedEntity implements Serializable { 
} 

Questa configurazione funziona per me, spero che sia stata utile.

+0

Grazie! Ci proverò al più presto. Nel frattempo, l'unica differenza evidente che vedo è che l'entità è serializzabile. È un requisito ora? –

+0

Penso che qui trovi la risposta. http://stackoverflow.com/questions/2020904/when-and-why-jpa-entities-should-implement-serializable-interface – lepike

+0

L'esempio fornito qui funziona, ma le entità non vengono memorizzate nella cache quando persistono. Solo quando viene interrogato. È così che deve funzionare? –

Problemi correlati