Using JPA 2.0 @Cacheable in J2SE with Spring, EHCache and Hibernate, without Hibernate specific annotations
I am trying to get JPA 2.0 Caching working in my Spring 3.0.5 application which uses Hibernate and EhCache. I do not wish to have my application bound to Hibernate and EhCache and wish to have it make use of pure JPA code only as far as possible.
I managed to get caching working with EHCache and Hibernate by setting the Hibernate specific @Cache
annotation on top of my entity classes and specifying org.hibernate.cacheable
as a query hint for my named queries.
However, when I try to switch those to @Ca开发者_JAVA技巧cheable(true)
and setting the query hint javax.persistence.cache.retrieveMode
to "CacheRetrieveMode.USE"
(I also tried just "USE"
) it doesn't work and my named query which should be cached is just getting retrieved again from the database. I am specifying these within the annotation of the NamedQuery itself using the hints = ...
I tried various combinations of <shared-cache-mode>
, ENABLE_SELECTIVE
, DISABLE_SELECTIVE
etc. but none seems to have any effect.
I am starting to suspect that this functionality is not available on J2SE. Am I missing something? Should I enable some extra annotation handler from the Spring application context?
Thanks.
Query caching with Hibernate JPA impl it's not possible without hint org.hibernate.cacheable up to current version 4.1. Of course you may store it in xml descriptors in named query defenitions and change it for different JPA providers (or store define hints for all variants). But in our projects we implement additional utility that adds hints to named query by external config (props). Eg:
ru.citc.jpa.queryhint.[query_name]=org.hibernate.cacheable\=true, javax.persistence.cache.retrieveMode\=USE,etc...
Entity cahcing may be configured by external properties. See there . Example:
<prop key="hibernate.ejb.classcache.ru.citc.migcredit.csrfront.model.Form">read-write,ScriptExecution</prop> <prop key="hibernate.ejb.collectioncache.ru.citc.migcredit.csrfront.model.Form.fields">read-write,ScriptExecution</prop> <prop key="hibernate.ejb.collectioncache.ru.citc.migcredit.csrfront.model.Form.constraints">read-only,ScriptDesignCollections</prop>
As result we have pure JPA code with external config for caching and other provider specific features. That work perfectly for Hibernate and EclipseLink. As additional bonus we have different caching strategies for different application modules (eg. admin web app do not cache metadata tables, but operator web app cache it read only).
Well, its not pure JPA, but I've used the EhCache annotation for Spring (http://code.google.com/p/ehcache-spring-annotations/wiki/UsingCacheable) and it works great. Annotate the DAO method you want to cache with @Cacheable(cacheName="myCache")
, configure the cache in your Spring configuration, and watch the DB calls disappear.
This looks to be working for me, with Hibernate ORM/EhCache 4.2.6.Final and Spring Framework 3.2.4.RELEASE:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="example.stackoverflow"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="false" />
<property name="showSql" value="true" />
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
<prop key="javax.persistence.sharedCache.mode">ENABLE_SELECTIVE</prop>
</props>
</property>
</bean>
I've annotated my Entity class with @javax.persistence.Cacheable
and I only see Hibernate logging SQL queries when getting something that's not in the cache. The key seems to be using the JPA property to specify whether to enable the cache rather than the hibernate-specific property.
精彩评论