2011-06-08 1 views
8

Le titre l'indique clairement: Je ne peux pas faire fonctionner le cache de second niveau pour JPA2/Hibernate 3.6.3. J'ai essayé beaucoup de bidouille pour le faire fonctionner. Mais je réussis seulement à faire fonctionner le cache de requête. Bien que Hibernate crée les caches (nom de l'instance), ils sont ignorés. Même les échecs ne sont pas enregistrés. Peut-être que c'est une incompatibilité de version. J'en ai essayé d'autres sans résultat. Et je ne me sens plus à la hauteur pour essayer toutes les permutations. :-PExemple de travail d'Hibernate 3.6.2 Mise en cache de 2ème niveau avec JPA2?

Je pose la question ici car certaines personnes semblent l'avoir fonctionné (dont les exemples j'ai essayé aussi). Peut-être qu'ils peuvent repérer l'erreur évidente que je fais.

Merci d'avance pour quiconque m'aide! :-)

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

<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 configuration

De cette façon, je peux vérifier l'utilisation des caches. Les caches sont créés (un pour chaque entité) et les deux caches de requête sont là aussi. Ces derniers se remplissent assez rapidement. Mais aucune des caches n'affiche des échecs ou des hits. Pas même les caches de requête.

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

Les caches d'entité sont ignorés. Ils doivent contenir au moins les entités enregistrées dans la base de données. Ou être récupéré avec des requêtes. Rien ne bouge là.

code Java Exemple

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 fusion fonctionne - parce qu'il ya des données dans la base de données. Et la recherche fonctionne parce que je reçois des objets avec des ID générés.

Les entités interrogées sont indexées dans la base de données.

WHODUNNIT?

+1

Avez-vous réellement marqué vos entités comme @Cacheable? –

+0

Oui. Et les bonnes caches popup dans JMX. Seules les entités ne sont pas mises en cache lorsqu'elles sont interrogées. Pas en cas de persistance/fusion. –

Répondre

4

trouvé le coupable - bien qu'il est assez contre-intuitif:

entités ne sont pas mises interrogées dans le cache de second niveau, sauf si vous fermez le gestionnaire de session/entité. Même si vous requery avec les mêmes objets, aucune mise en cache ne se produira.

J'ai un long processus par lots dans lequel de nombreux objets de référence sont créés et réutilisés. Si je garde le même gestionnaire d'entité tout le long, je ne vois pas la fin du processus. Si je recrée le gestionnaire d'entité à chaque cycle, l'application vole.

Je pensais qu'il y avait quelque chose comme un cache de 1er niveau - le contexte de persistance?

4

Un de mes projets utilise ehcache + hibernate + jpa2. Je te dis ma configuration. J'espère que cela vous aide.

versions cadre (de dépendance Maven):

<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> 

Les deux versions sont testées en veille prolongée, mais je ne pas utiliser les api jpa2 de veille prolongée.

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> 

Enfin, vous devez annoter votre entité classe cachable. Voici un exemple:

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

Cette configuration fonctionne pour moi, j'espère que c'était utile.

+0

Merci! Je vais essayer avec ça dès que possible. En attendant, la seule différence notable que je vois est que l'entité est sérialisable. Est-ce une exigence maintenant? –

+0

Je pense que vous pouvez trouver ici la réponse. http://stackoverflow.com/questions/2020904/when-and-why-jpa-entities-should-implement-serializable-interface – lepike

+0

L'exemple fourni ici fonctionne, mais les entités ne sont pas mises en cache lorsqu'elles persistent. Seulement quand on est interrogé. Est-ce la façon dont cela est censé fonctionner? –

Questions connexes