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);
}
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 thepersistence.xml
(or the equivalentjavax.persistence.sharedCache.mode
when creating theEntityManagerFactory
).Below, a sample
persistence.xml
with the relevant element and properties:Note that I've seen at least one issue HHH-5303 related to caching. So the above is not guaranteed :)
References
For those who use Spring config instead of
persistence.xml
, here is a sample:Also note that if you're using
@Cacheable
annotations, you can only use a default cache concurrency strategy, which is determined by thegetDefaultAccessType()
method of theRegionFactory
. In case of EhCache it's READ_WRITE. If you want to use another strategy, you have to use Hibernate's@Cache
annotations.