This post will go through how to setup the Hibernate Second-Level and Query caches, how they work and what are their most common pitfalls.

The Hibernate second level cache is an application level cache for storing entity data. The query cache is a separate cache that stores query results only.

The two caches really go together, as there are not many cases where we would like to use one without the other. When well used these caches provide improved performance in a transparent way, by reducing the number of SQL statements that hit the database.

How does the second level-cache work?

The second level cache stores the entity data, but NOT the entities themselves. The data is stored in a 'dehydrated' format which looks like a hash map where the key is the entity Id, and the value is a list of primitive values.

Here is an example on how the contents of the second-level cache look:

*-----------------------------------------*
| Person Data Cache |
|-----------------------------------------|
| 1 -> [ "John" , "Q" , "Public" , null ] |
| 2 -> [ "Joey" , "D" , "Public" , 1 ] |
| 3 -> [ "Sara" , "N" , "Public" , 1 ] |
*-----------------------------------------*

The second level cache gets populated when an object is loaded by Id from the database, using for example entityManager.find(), or when traversing lazy initialized relations.

How does the query cache work?

The query cache looks conceptually like an hash map where the key is composed by the query text and the parameter values, and the value is a list of entity Id's that match the query:

*----------------------------------------------------------*
| Query Cache |
|----------------------------------------------------------|
| ["from Person where firstName=?", ["Joey"] ] -> [1, 2] ] |
*----------------------------------------------------------*

Some queries don't return entities, instead they return only primitive values. In those cases the values themselves will be stored in the query cache. The query cache gets populated when a cacheable JPQL/HQL query gets executed.

What is the relation between the two caches?

If a query under execution has previously cached results, then no SQL statement is sent to the database. Instead the query results are retrieved from the query cache, and then the cached entity identifiers are used to access the second level cache.

If the second level cache contains data for a given Id, it re-hydrates the entity and returns it. If the second level cache does not contain the results for that particular Id, then an SQL query is issued to load the entity from the database.

How to setup the two caches in an application

The first step is to include the hibernate-ehcache jar in the classpath:

<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>SOME-HIBERNATE-VERSION</version>
</dependency>

The following parameters need to be added to the configuration of your EntityManagerFactory or SessionFactory:

<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
<prop key="net.sf.ehcache.configurationResourceName">/your-cache-config.xml</prop>

Prefer using EhCacheRegionFactory instead of SingletonEhCacheRegionFactory. Using EhCacheRegionFactory means that Hibernate will create separate cache regions for Hibernate caching, instead of trying to reuse cache regions defined elsewhere in the application.

The next step is to configure the cache regions settings, in file your-cache-config.xml:

<?xml version="1.0" ?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
updateCheck="false"
xsi:noNamespaceSchemaLocation="ehcache.xsd" name="yourCacheManager"> <diskStore path="java.io.tmpdir"/> <cache name="yourEntityCache"
maxEntriesLocalHeap="10000"
eternal="false"
overflowToDisk="false"
timeToLiveSeconds="86400" /> <cache name="org.hibernate.cache.internal.StandardQueryCache"
maxElementsInMemory="10000"
eternal="false
timeToLiveSeconds="86400"
overflowToDisk="false"
memoryStoreEvictionPolicy="LRU" /> <defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToLiveSeconds="86400"
overflowToDisk="false"
memoryStoreEvictionPolicy="LRU" />
</ehcache>

If no cache settings are specified, default settings are taken, but this is probably best avoided. Make sure to give the cache a name by filling in the name attribute in the ehcache element.

Giving the cache a name prevents it from using the default name, which might already be used somewhere else on the application.

Using the second level cache

The second level cache is now ready to be used. In order to cache entities, annotate them with the @org.hibernate.annotations.Cacheannotation:

@Entity
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY,
region="yourEntityCache")
public class SomeEntity {
...
}

Associations can also be cached by the second level cache, but by default this is not done. In order to enable caching of an association, we need to apply @Cache to the association itself:

@Entity
public class SomeEntity {
@OneToMany
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY,
region="yourCollectionRegion")
private Set<OtherEntity> other;
}

Using the query cache

After configuring the query cache, by default no queries are cached yet. Queries need to be marked as cached explicitly, this is for example how a named query can be marked as cached:

@NamedQuery(name="account.queryName",
query="select acct from Account ...",
hints={
@QueryHint(name="org.hibernate.cacheable",
value="true")
}
})

And this is how to mark a criteria query as cached:

List cats = session.createCriteria(Cat.class)
.setCacheable(true)
.list();

The next section goes over some pitfalls that you might run into while trying to setup these two caches. These are behaviors that work as designed but still can be surprising.

Pitfall 1 - Query cache worsens performance causing a high volume of queries

There is an harmful side-effect of how the two caches work, that occurs if the cached query results are configured to expire more frequently than the cached entities returned by the query.

If a query has cached results, it returns a list of entity Id's, that is then resolved against the second level cache. If the entities with those Ids where not configured as cacheable or if they have expired, then a select will hit the database per entity Id.

For example if a cached query returned 1000 entity Ids, and non of those entities where cached in the second level cache, then 1000 selects by Id will be issued against the database.

The solution to this problem is to configure query results expiration to be aligned with the expiration of the entities returned by the query.

Pitfall 2 - Cache limitations when used in conjunction with @Inheritance

It is currently not possible to specify different caching policies for different subclasses of the same parent entity.

For example this will not work:

@Entity
@Inheritance
@Cache(CacheConcurrencyStrategy.READ_ONLY)
public class BaseEntity {
...
} @Entity
@Cache(CacheConcurrencyStrategy.READ_WRITE)
public class SomeReadWriteEntity extends BaseEntity {
...
} @Entity
@Cache(CacheConcurrencyStrategy.TRANSACTIONAL)
public class SomeTransactionalEntity extends BaseEntity {
...
}

In this case only the @Cache annotation of the parent class is considered, and all concrete entities have READ_ONLY concurrency strategy.

Pitfall 3 - Cache settings get ignored when using a singleton based cache

It is advised to configure the cache region factory as a EhCacheRegionFactory, and specify an ehcache configuration via net.sf.ehcache.configurationResourceName.

There is an alternative to this region factory which is SingletonEhCacheRegionFactory. With this region factory the cache regions are stored in a singleton using the cache name as a lookup key.

The problem with the singleton region factory is that if another part of the application had already registered a cache with the default name in the singleton, this causes the ehcache configuration file passed via net.sf.ehcache.configurationResourceName to be ignored.

Conclusion

The second level and query caches are very useful if set up correctly, but there are some pitfalls to bear in mind in order to avoid unexpected behaviors. All in all it's a feature that works transparently and that if well used can increase significantly the performance of an application.

Please let us know in the comments bellow your own experience and pitfalls you have encountered. Thanks for reading.

reference from :http://blog.jhades.org/setup-and-gotchas-of-the-hibernate-second-level-and-query-caches/

Pitfalls of the Hibernate Second-Level / Query Caches--reference的更多相关文章

  1. 分享知识-快乐自己:Hibernate 中Criteria Query查询详解

    1):Hibernate 中Criteria Query查询详解 当查询数据时,人们往往需要设置查询条件.在SQL或HQL语句中,查询条件常常放在where子句中. 此外,Hibernate还支持Cr ...

  2. Hibernate中的query.setFirstResult(),query.setMaxResults();

    一.query.scroll()和query.setFirstResult(),query.setMaxResults();这两种方法都可以取到一定范围内的数据,用来数据分页显示.那么两者区别,以及两 ...

  3. Hibernate 中Criteria Query查询详解【转】

    当查询数据时,人们往往需要设置查询条件.在SQL或HQL语句中,查询条件常常放在where子句中.此外,Hibernate还支持Criteria查询(Criteria Query),这种查询方式把查询 ...

  4. Hibernate 学习之Query查询(HQL查询)

    package com.itcloud.test; import com.itcloud.pojo.Dept; import org.hibernate.Session; import org.hib ...

  5. hibernate中调用query.list()而出现的黄色警告线

    使用hibernate的时候会用到hql语句查询数据库, 那就一定会用到query.list();这个方法, 那就一定会出现一个长长的黄色的警告线, 不管你想尽什么办法, 总是存在, 虽然说这个黄色的 ...

  6. Hibernate中的Query对象查询所有记录

    映射文件,核心文件,实体类,工具类的内容都不变直接看测试方法中的代码: package com.yinfu.test; import java.util.List; import org.hibern ...

  7. [ElasticSearch]Java API 之 词条查询(Term Level Query)

    1. 词条查询(Term Query)  词条查询是ElasticSearch的一个简单查询.它仅匹配在给定字段中含有该词条的文档,而且是确切的.未经分析的词条.term 查询 会查找我们设定的准确值 ...

  8. Hibernate中关于Query返回查询结果是类名的问题

    query.list返回的是一个装有类的信息的集合,而不装有数据库信息的集合.如下图 运行结果为:   因为得到的集合是类,所以要将list泛型设为那个类,并且将得到的集合进行.get(x).getx ...

  9. Hibernate中的Query

    //1:创建query对象,方法里面写hql语句 Query query = session.createQuery("from User"); //2:利用query对象中的方法 ...

随机推荐

  1. java jvm学习笔记二(类装载器的体系结构)

    欢迎装载请说明出处:http://blog.csdn.net/yfqnihao                 在了解java虚拟机的类装载器之前,有一个概念我们是必须先知道的,就是java的沙箱,什 ...

  2. 7、四大组件之二-Service高级

    一.Native Service 1>什么是Native Service 使用JNI编写,在系统启动完成之前启动的系统级服务. 2>哪些服务是Native Service ACCESSIB ...

  3. POJ 3126 Prime Path BFS搜索

    题意:就是找最短的四位数素数路径 分析:然后BFS随便搜一下,复杂度最多是所有的四位素数的个数 #include<cstdio> #include<algorithm> #in ...

  4. 利用迅雷提供的接口从磁力链得到bt种子文件

    本地下载工具的磁力链下载速度不给力,而百度云盘有提供离线下载服务,相当于就是直接到服务器取个链接而已.但这需要bt文件,而我只有链力链.网上搜了一下,可以从磁力链构造一个bt文件的下载地址,用pyth ...

  5. MATLAB将批量的图片保存为mat文件

    clc; clear all; num = 10; for i = 1 : num IM = imread(sprintf('E:\\TEST\\PtzTEST2015-8-9\\image1280x ...

  6. HDU-4705 Y 树形DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4705 题意:给一颗树,从树上任意选择3个点{A,B,C},要求他们不在一条链上,求总共的数目. 容易想 ...

  7. Delphi XE5 安卓手机要求

    1 ARMv7 的 CPU v6 的肯定不支持. 2 黑屏是因为你的手机 CPU 不支持 NEON 特性.或者是 T2 海思 CPU .这 2 个不支持. 3 系统版本  2.3.3 到 2.3.9 ...

  8. UVa 二分图匹配 Examples

    这些都是刘汝佳的算法训练指南上的例题,基本包括了常见的几种二分图匹配的算法. 二分图是这样一个图,顶点分成两个不相交的集合X , Y中,其中同一个集合中没有边,所有的边关联在两个集合中. 给定一个二分 ...

  9. C++学习笔记(九):作用域和命名空间

    作用域 作用域规则告诉我们一个变量的有效范围,它在哪儿创建,在哪儿销毁(也就是说超出了作用域).变量的有效作用域从它的定义点开始,到和定义变量之前最邻近的开括号配对的第一个闭括号.也就是说,作用域由变 ...

  10. C++学习笔记(五):指针和引用

    声明指针: //指针声明 * 号左右的空格是可选的,下面的定义都是正确的 int *pointer1; int* pointer2; int*pointer3; int * pointer4; //注 ...