Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Working example of Hibernate 3.6.2 2nd level caching with JPA2?

The title obviously states it : I can't make the second-level cache work for JPA2/Hibernate 3.6.3.

I've been trying many a hack to make it work. But I'm only succeeding in having the query cache working. Although Hibernate creates the caches (name of the instance), they're ignored. Even misses are not registered. Maybe it's a version incompatibility. I've tried some others with no result. And I don't feel up to the task anymore to try all permutations. :-P

I'm asking the question here as some people seem to have it working (whose examples I tried also). Maybe they can spot the obvious error I'm making.

Thanks in advance for anybody helping me out ! :-)

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 setup

This way I can check the usage of the caches. The caches are created (one for each entity) and the two query caches are there too. The latter are filling up pretty fast. But none of the caches display any misses or hits. Not even the query caches.

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

The entity caches are ignored. They should contain at least the entities that are saved into the database. Or being retrieved with queries. Nothing moves there.

Sample Java code

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();

The merge works - because there's data into the database. And the find works because I'm getting objects with generated id's.

The queried entities are indexed on the database.

WHODUNNIT ?

like image 764
Jan Goyvaerts Avatar asked Jun 08 '11 16:06

Jan Goyvaerts


People also ask

How Hibernate 2nd Level cache works?

This cache only works at a session level, meaning each session object caches data independently, so there is no sharing of cached data across sessions, and the cached data is deleted when the session closes. This makes the cache only useful for repeated queries in the same session.

What is L1 and L2 cache in Hibernate?

By default, Hibernate only uses per-session (L1) cache, so, objects, cached in one session, are not seen in another. However, an L2 cache may be used, in which the cached objects are seen for all sessions that use the same L2 cache configuration.


1 Answers

One of my project uses ehcache + hibernate + jpa2. I tell you my configuration. Hope it helps you.

framework versions (maven dependency):

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

The two hibernate versions are tested, but I don't use the hibernate jpa2 api.

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>

Finally you should annotate your cachable entity class. Here is an example:

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

This configuration works for me, hope it was useful.

like image 66
lepike Avatar answered Sep 28 '22 21:09

lepike