How to use JPA2 @Cacheable instead of Hibernate @Cache

Typically, I use Hibernate @Cache (using = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) to cache the @Entity class, and it works well.

There is another @Cacheable annotation in JPA2 that seems to match functionality with Hibernate @Cache. To make the entity class independent of the hibernate package, I want to try. But I can’t make it work. Every time a simple id request still ends up in the database.

Can someone tell me where it goes wrong? Thank.

Entity Class:

@Entity //@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) @Cacheable(true) public class User implements Serializable { // properties } 

Testing Class:

 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations={"classpath:app.xml"}) @TransactionConfiguration(transactionManager="transactionManager") public class UserCacheTest { @Inject protected UserDao userDao; @Transactional @Test public void testGet1() { assertNotNull(userDao.get(2L)); } @Transactional @Test public void testGet2() { assertNotNull(userDao.get(2L)); } @Transactional @Test public void testGet3() { assertNotNull(userDao.get(2L)); } } 

The test result shows each access level "get" (with hibernate.show_sql = true).

Persistence.xml:

 <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/> <property name="hibernate.show_sql" value="true"/> <property name="hibernate.format_sql" value="true" /> <property name="hibernate.use_outer_join" value="true"/> <property name="hibernate.cache.provider_class" value="org.hibernate.cache.SingletonEhCacheProvider"/> <property name="hibernate.cache.use_second_level_cache" value="true"/> <property name="hibernate.cache.use_query_cache" value="true"/> 

JPA Code:

 @Override public T get(Serializable id) { return em.find(clazz, id); } 
+42
caching orm hibernate jpa
Sep 08 '10 at 1:20
source share
2 answers

According to the JPA 2.0 specification, if you want to selectively cache objects using the @Cacheable annotation, you must specify <shared-cache-mode> in persistence.xml (or the equivalent of javax.persistence.sharedCache.mode when creating an EntityManagerFactory ).

Below is a sample persistence.xml with the corresponding element and properties:

 <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="FooPu" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> ... <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode> <properties> ... <property name="hibernate.cache.provider_class" value="org.hibernate.cache.SingletonEhCacheProvider"/> <property name="hibernate.cache.use_second_level_cache" value="true"/> <property name="hibernate.cache.use_query_cache" value="true"/> </properties> </persistence-unit> </persistence> 

Note that I have seen at least one HHH-5303 caching issue. Thus, the above is not guaranteed :)

References

  • Hibernate EntityManager Reference Guide
  • JPA 2.0 Specification
    • Section 3.7.1 "Shared Cache Mode Element"
    • Section 11.1.7 "Cached Annotation"
+41
Sep 08 2018-10-10T00:
source share
β€” -

For those using Spring config instead of persistence.xml , here is an example:

 <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="database" value="MYSQL"/> <property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect"/> <property name="showSql" value="true"/> <property name="generateDdl" value="false"/> </bean> </property> <property name="packagesToScan" value="com.mycompany.myproject.domain"/> <property name="jpaPropertyMap"> <map> <entry key="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory"/> <entry key="hibernate.cache.use_second_level_cache" value="true"/> <entry key="hibernate.cache.use_query_cache" value="true"/> <entry key="javax.persistence.sharedCache.mode" value="ENABLE_SELECTIVE" /> </map> </property> </bean> 

Also note that if you use @Cacheable annotations, you can only use the default concurrency cache strategy, which is determined by the getDefaultAccessType() method for RegionFactory . In the case of EhCache READ_WRITE . If you want to use a different strategy, you should use Hibernate @Cache annotations.

+10
Mar 27 '14 at 10:12
source share



All Articles