Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use JPA2's @Cacheable instead of Hibernate's @Cache

Typically , I use Hibernate's @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) to cache an @Entity class , and it works well.

In JPA2 , there's another @Cacheable annotation that seems to be the same functionality with Hibernate's @Cache. To make my entity class independent of hibernate's package , I want to give it a try. But I cannot make it work. Each time a simple id query still hits the DB.

Can anybody tell me where goes wrong ? Thanks.

Entity class :

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

Test 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 "get" hits DB layer (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); } 
like image 800
smallufo Avatar asked Sep 08 '10 01:09

smallufo


People also ask

How hibernate first level cache works?

First Level Cache: Hibernate first level cache is associated with the Session object. Hibernate first level cache is enabled by default and there is no way to disable it. However hibernate provides methods through which we can delete selected objects from the cache or clear the cache completely.

How do I clear hibernate cache in spring boot?

We can use session clear() method to clear the cache i.e delete all the objects from the cache. We can use session contains() method to check if an object is present in the hibernate cache or not, if the object is found in cache, it returns true or else it returns false.

What is CacheConcurrencyStrategy?

Interface CacheConcurrencyStrategy. All Known Implementing Classes: NonstrictReadWriteCache, ReadOnlyCache, ReadWriteCache, TransactionalCache public interface CacheConcurrencyStrategy. Implementors manage transactional access to cached data. Transactions pass in a timestamp indicating transaction start time.


1 Answers

According to the JPA 2.0 specification, if you want to selectively cache entities using the @Cacheable annotation, you're supposed to specify a <shared-cache-mode> in the persistence.xml (or the equivalent javax.persistence.sharedCache.mode when creating the EntityManagerFactory).

Below, a sample persistence.xml with the relevant 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've seen at least one issue HHH-5303 related to caching. So the above is not guaranteed :)

References

  • Hibernate EntityManager reference guide
    • 2.2.1 Packaging
  • JPA 2.0 Specification
    • Section 3.7.1 "The shared-cache-mode Element"
    • Section 11.1.7 "Cacheable Annotation"
like image 189
Pascal Thivent Avatar answered Oct 01 '22 20:10

Pascal Thivent