Hibernate性能优化 --- 缓存管理
一 hibernate内部缓存的分析
1、一级缓存 --- Session级别的缓存概念
Session级别的缓存由Hibernate自动管理的,一般情况下无需进行干预,当应用程序调用Session的CURD方法以及调用查询接口的list等等方法时,如果缓存中还不存在响应的对象,Hibernate就会把该对象加入到Session缓存中。当Hibernate清理缓存时,Hibernate会根据缓存中的状态变化来同步数据库中的数据状态,在Session关闭时,会清空Session缓存中的所有对象。
2.测试缓存的存在
public static User getUser(int id) {
Session session = null;
try {
session = HibernateUtil.getSession();
//第一次查询的时候从数据库中查询,并且把数据放到缓存中
User user = (User) session.get(User.class, id);
System.out.println("----------------");
//在第二次查询的时候没有输出查询的语句,是因为是从缓存中查的而不是数据库
user = (User) session.get(User.class, id);
} finally {
if (session != null) {
session.close();
}
}
}
注:输出的结果只有一条select语句,原因就是第一次查询的时候从数据库中查询,并且把数据放到缓存中,第二次查询的时候没有输出查询的语句,是因为是从缓存中查的而不是数据库
3.测缓存的生命周期
public static User getUser(int id) {
Session session = null;
try {
session = HibernateUtil.getSession();
//第一次查询的时候从数据库中查询,并且把数据放到缓存中
User user = (User) session.get(User.class, id);
} finally {
if (session != null) {
session.close();
}
}
try {
session = HibernateUtil.getSession();
//第一次查询的时候从数据库中查询,并且把数据放到缓存中
User user = (User) session.get(User.class, id);
return user;
} finally {
if (session != null) {
session.close();
}
}
注:以上的代码结果是有两条select语句,是因为在session关闭之后一级缓存也就关闭了,当再次开启的获取连接的时候,又是一次查询
4.缓存中是设计的三个操作:
(1)把数据放入到缓存的操作,当再调用save upate saveOrupdate load get list.iterate lock这些方法都可以将数据放到一级缓存中,为了优化查询,但是一级缓存不能控制缓存的数据,所以要注意大批量操作
(2)从缓存中获取数据 查询的时候
get() load()方法先去缓存中查询数据,如果缓冲中有对象直接返回该对象,如果没有,就去数据库中查询数据
Query接口的查询(list方法)不从 缓存中提取数据,直接访问的是数据库,但是查询的数据会存放到缓存中
Criteria不从缓存中提取数据
(3)删除缓存中无效的数据
5.清除一级缓存
session.evict(user);//清除缓存中指定的对象
session.clear();//清除一级缓存中的所有对象
但是绝大多数情况下不需要人为的清理,Hibernate会自行处理
6.一级缓存的缺陷
(1)一级缓存没有保护,不能控制缓存的数据,所以要注意在放入缓存中数据的时候要注意,如果过大,可人为的清理缓存
(2)共享的范围太小,不能实现共享。因为一级缓存是session的缓存,session的存在时间是一次会话。
2.二级缓存 --- SessionFactory级别的缓存
1.配置二级缓存 要在hibernate.cfg.xml中配置,主要告诉hibernate第三方的缓存的提供者是谁,
(1)二级缓存的打开 hibernate.cache.use_second_level_cache
<property name="hibernate.cache.use_second_level_cache">true</property>
决定要不要打开二级缓存,这个属性的默认值为真,该属性不配置也可以
(2)二级缓存的提供者 hibernate.cache.provider_class
<property name="hibernate.cache.provider_class">org.hibernate.cache.OSCacheProvider</property>
Cache的提供者是org.hibernate.cache.OSCacheProv,并且将oscache】需要的jar包构建到lib下
需要将oscache.properties拷贝到classPath路径下,也就是src下,文件名字和路径不可以该
(3)告诉hibernate哪些类是需要放入二级缓存的 <class-cach>标签
方法一:
<class-cache usage="read-only" class="com.hbsi.domain.User"/>
包名必须是完全限定名
(3).1缓存的使用策略
Usage:read-only 只读的缓存,效率是最高的,但是有一个限制,当缓存中的数据被更新的话就会抛异常
read-write:可读取的缓存,可以并发的修改数据,但是会付出代价的,效率会受到影响
nostrict-read-writer 不严格的缓存,不对数据进行加锁,效率高点
transactional 事务型的缓存,一般的缓存框架不支持
方法二:
在类的映射文件中告诉hibernate,在<class>类的标签中放入
<cache usage="read-only"/>
2.测试二级缓存
实例分析:
public static User getUser(int id) {
Session session = null;
try {
session = HibernateUtil.getSession();
User user = (User) session.get(User.class, id);//数据库中查找
user = (User) session.load(User.class, id);//一级缓存查询
} finally {
if (session != null) {
session.close();
}
}
try {
session = HibernateUtil.getSession();
User user = (User) session.get(User.class, id);
//二级缓存中查: 先从一级缓存中查找,再从二级缓存中查找
return user;
} finally {
if (session != null) {
session.close();
}
}
}
注:
执行结果为输出一条select语句,因为是从二级缓存后中查找的
当清除缓存的时候,也是输出一条语句,因为清除的缓存只是清除一级缓存的
3.得到缓存中的命中
命中:如果查询的数据是从二级缓存中查找出来的话是命中
miss错过:如果查询的数据是从数据库中查询的
在Statistics st = SessionFactory.getStatistics()得到缓存的统计信息
表示在工作的工程中,可以产生统计信息
<property name="hibernate.generate_statistics">true</property>
通过调用
Statistics
statistics = HibernateUtil.getSessionFactory().getStatistics();
得到统计的所有信息,为:
Statistics[start time=1324006126656,sessions opened=3,sessions closed=3,transactions=1,successful transactions=1,optimistic lock failures=0,flushes=1,connections obtained=2,statements prepared=2,statements closed=2,second level cache puts=1,second level cache hits=1,second level cache misses=1,entities loaded=1,entities updated=0,entities inserted=1,entities deleted=0,entities fetched=0,collections loaded=0,collections updated=0,collections removed=0,collections recreated=0,collections fetched=0,queries executed to database=0,query cache puts=0,query cache hits=0,query cache misses=0,max query time=0]
注:
opens = 3 是session被打开了三次
transactions成功的事务数
second level cache puts=1 二级缓存放入的次数
second level cache hits=1 二级缓存命中的次数
second level cache misses=1 二级缓存错过的次数
放入:
save可以把对象放入二级缓存,但是主键不是native,如果不是用native,就可以放入二级缓存。
命中:命中是从二级缓存中去吃来的
错过:是在从二级缓存中查询的时候没有存在的数据