hibernate的二级缓存----collection和query的二级缓存
collection二级缓存:
不使用集合的二级缓存时:
运行下面的代码:
@Test
public void testCollectionSecondLevelCache1(){
Department dept = (Department) session.get(Department.class, 3);
System.out.println(dept.getId()+" "+dept.getName());
System.out.println(dept.getEmps().size()); transaction.commit();
session.close(); session = sessionFactory.openSession();
transaction = session.beginTransaction(); Department dept2 = (Department) session.get(Department.class,3);
Set<Employee> emps=dept2.getEmps();
for(Employee employee:emps){
System.out.println(employee.getId()+" " +employee.getName());
}
}
产生的结果如下:
Hibernate:
select
department0_.ID as ID1_0_0_,
department0_.NAME as NAME2_0_0_
from
GG_DEPARTMENT department0_
where
department0_.ID=?
3 B
Hibernate:
select
emps0_.DEPT_ID as DEPT_ID5_0_1_,
emps0_.ID as ID1_1_1_,
emps0_.ID as ID1_1_0_,
emps0_.NAME as NAME2_1_0_,
emps0_.SALARY as SALARY3_1_0_,
emps0_.EMAIL as EMAIL4_1_0_,
emps0_.DEPT_ID as DEPT_ID5_1_0_
from
GG_EMPLOYEE emps0_
where
emps0_.DEPT_ID=?
3
--------------------------------------------------
Hibernate:
select
department0_.ID as ID1_0_0_,
department0_.NAME as NAME2_0_0_
from
GG_DEPARTMENT department0_
where
department0_.ID=?
Hibernate:
select
emps0_.DEPT_ID as DEPT_ID5_0_1_,
emps0_.ID as ID1_1_1_,
emps0_.ID as ID1_1_0_,
emps0_.NAME as NAME2_1_0_,
emps0_.SALARY as SALARY3_1_0_,
emps0_.EMAIL as EMAIL4_1_0_,
emps0_.DEPT_ID as DEPT_ID5_1_0_
from
GG_EMPLOYEE emps0_
where
emps0_.DEPT_ID=?
5 EE
7 GG
6 FF
1如果Session没有关闭的话应该是发送两条select语句的吧,因为Session的缓存中已经初始化了department和employee对象啦,但是Session关闭后,Session的一级缓存没有了吧,所以此时的department和employee对象都是游离对象,当需要要再次获得时必须发送select语句给数据吖
但是如果我们启用了集合的二级缓存呢??
集合二级缓存的操作步骤:
I. 配置对集合使用二级缓存
<collection-cache usage="read-write" collection="com.atguigu.hibernate.entities.Department.emps"/>
也可以在 .hbm.xml 文件中进行配置
<set name="emps" table="GG_EMPLOYEE" inverse="true" lazy="true">
<cache usage="read-write"/>
<key>
<column name="DEPT_ID" />
</key>
<one-to-many class="com.atguigu.hibernate.entities.Employee" />
</set>
II. 注意: 还需要配置集合中的元素对应的持久化类也使用二级缓存! 否则将会多出 n 条 SQL 语句.(集合缓存依赖于对持久化类的二级缓存)
例如在Hibernate.cfg.xml文件中配置集合的二级缓存:
<class-cache usage="read-write" class="com.atguigu.hibernate.entities.Employee"/>
<class-cache usage="read-write" class="com.atguigu.hibernate.entities.Department"/>
<collection-cache usage="read-write" collection="com.atguigu.hibernate.entities.Department.emps"/>
代码示例:
使用了集合二级缓存后结果为这个:
Hibernate:
select
department0_.ID as ID1_0_0_,
department0_.NAME as NAME2_0_0_
from
GG_DEPARTMENT department0_
where
department0_.ID=?
3 B
Hibernate:
select
emps0_.DEPT_ID as DEPT_ID5_0_1_,
emps0_.ID as ID1_1_1_,
emps0_.ID as ID1_1_0_,
emps0_.NAME as NAME2_1_0_,
emps0_.SALARY as SALARY3_1_0_,
emps0_.EMAIL as EMAIL4_1_0_,
emps0_.DEPT_ID as DEPT_ID5_1_0_
from
GG_EMPLOYEE emps0_
where
emps0_.DEPT_ID=?
3
--------------------------------------------------
6 FF
5 EE
7 GG
查询缓存:
查询缓存是二级缓存的一种用法
查询缓存(Query Cache):
对于经常使用的查询语句,如果启用了查询缓存,当第一次执行查询语句时,Hibernate会把 查询结果存放在二级缓存中。以后再次执行该查询语句时,只需从缓存中获得查询结果,从而提高查询性能。
查询缓存适用于以下场合: 1在应用程序运行时经常使用的查询语句。 2 很少对与查询语句关联的数据库数据进行插入、删除或更新操作。
在hibernate的使用中,大家多数时间都在讨论一级缓存和二级缓存,而往往忽略了查询缓存。其实hibernate的查询缓存在使用过程中也起着同样重要的作用。hibernate的查询缓存是主要是针对普通属性结果集的缓存, 而对于实体对象的结果集只缓存id。在一级缓存,二级缓存和查询缓存都打开的情况下作查询操作时这样的:
查询普通属性---》会先到查询缓存中取,如果没有,则查询数据库;
查询实体---》 会先到查询缓存中取id,如果有,则根据id到缓存(一级/二级)中取实体,如果缓存中取不到实体,再查询数据库。
1查询缓存是属于二级缓存的一个子类别,所以查询缓存依赖于二级缓存,所以在使用查询缓存之前,必须配置好二级缓存,二级缓存上面有说,这里就不提了
2在 hibernate 配置文件中声明开启查询缓存
<property name="cache.use_query_cache">true</property>
3调用 Query 或 Criteria 的 setCacheable(true) 方法,启用当前(就是在你需要的查询语句后执行 setCacheable(true)方法)的查询缓存
例子说明:
测试代码:
@Test
public void testQueryCache(){
Query query = session.createQuery("FROM Employee");
List<Employee> emps = query.list();
System.out.println(emps.size());
System.out.println(emps.iterator().next().getClass()); emps = query.list();
System.out.println(emps.size());
}
运行结果:
Hibernate:
select
employee0_.ID as ID1_1_,
employee0_.NAME as NAME2_1_,
employee0_.SALARY as SALARY3_1_,
employee0_.EMAIL as EMAIL4_1_,
employee0_.DEPT_ID as DEPT_ID5_1_
from
GG_EMPLOYEE employee0_
25
class com.atguigu.hibernate.entities.Employee
Hibernate:
select
employee0_.ID as ID1_1_,
employee0_.NAME as NAME2_1_,
employee0_.SALARY as SALARY3_1_,
employee0_.EMAIL as EMAIL4_1_,
employee0_.DEPT_ID as DEPT_ID5_1_
from
GG_EMPLOYEE employee0_
25
在这里两次我都是执行同样的HQL语句进行查询,但是Hibernate却帮我发送了两条select语句,有一条是不是就是多余的啦?这就说明了在默认情况下, 设置的缓存对 HQL 及 QBC 查询时无效的, 但可以通过设置查询缓存的方式使其生效,(注意QBC查询也需要这样去设置)
启动了查询缓存后运行结果为:
Hibernate:
select
employee0_.ID as ID1_1_,
employee0_.NAME as NAME2_1_,
employee0_.SALARY as SALARY3_1_,
employee0_.EMAIL as EMAIL4_1_,
employee0_.DEPT_ID as DEPT_ID5_1_
from
GG_EMPLOYEE employee0_
25
class com.atguigu.hibernate.entities.Employee
25
只发送了一条select语句,那这样是不是大大减轻了我的程序的负担了吧
@Test
public void testQueryCache(){
Query query = session.createQuery("FROM Employee e where e.id=1");
query.setCacheable(true); List<Employee> emps = query.list();
System.out.println(emps.size());
System.out.println(emps.iterator().next().getClass()); Employee employee=new Employee(); employee.setEmail("sdkfjsd@qq.com");
employee.setName("jeremy");
employee.setSalary(8000F);
session.save(employee); emps = query.list();
System.out.println(emps.size()); //Criteria criteria = session.createCriteria(Employee.class);
//criteria.setCacheable(true);
}
运行结果:
Hibernate:
select
employee0_.ID as ID1_1_,
employee0_.NAME as NAME2_1_,
employee0_.SALARY as SALARY3_1_,
employee0_.EMAIL as EMAIL4_1_,
employee0_.DEPT_ID as DEPT_ID5_1_
from
GG_EMPLOYEE employee0_
where
employee0_.ID=10
1
class com.atguigu.hibernate.entities.Employee
Hibernate:
insert
into
GG_EMPLOYEE
(NAME, SALARY, EMAIL, DEPT_ID)
values
(?, ?, ?, ?)
Hibernate:
select
employee0_.ID as ID1_1_,
employee0_.NAME as NAME2_1_,
employee0_.SALARY as SALARY3_1_,
employee0_.EMAIL as EMAIL4_1_,
employee0_.DEPT_ID as DEPT_ID5_1_
from
GG_EMPLOYEE employee0_
where
employee0_.ID=10
1
我在进行了第一次HQL查询后又对了数据表进行了增加操作了,此时的数据表已经发生了改变了,此时查询缓存被关闭了(就算更新操作对我HQL语句查询的结果没影响,但是查询缓存还是被关闭了)
如果查询缓存没有被关闭,那已是发送一条select语句和一条insert语句,但是现在是发送了两条select语句,一条insert语句 ,所以证明了,当查询缓存相关的表更新后,
hibernate的二级缓存----collection和query的二级缓存的更多相关文章
- Hibernate缓存简介和对比、一级缓存、二级缓存详解
一.hibernate缓存简介 缓存的范围分为3类: 1.事务范围(单Session即一级缓存) 事务范围的缓存只能被当前事务访问,每个事务都有各自的缓存,缓存内的数据通常采用相互关联的对象 ...
- Java三大框架之——Hibernate中的三种数据持久状态和缓存机制
Hibernate中的三种状态 瞬时状态:刚创建的对象还没有被Session持久化.缓存中不存在这个对象的数据并且数据库中没有这个对象对应的数据为瞬时状态这个时候是没有OID. 持久状态:对象经过 ...
- Hibernate第七篇【对象状态、一级缓存】
前言 本博文主要讲解Hibernate的细节-->对象的状态和一级缓存- 对象状态 Hibernate中对象的状态: - 临时/瞬时状态 - 持久化状态 - 游离状态 学习Hibernate的对 ...
- mybatis由浅入深day02_7.4mybatis整合ehcache_7.5二级缓存应用场景_7.6二级缓存局限性
7.4 mybatis整合ehcache EhCache 是一个纯Java的进程内缓存框架,是一种广泛使用的开源Java分布式缓存,具有快速.精干等特点,是Hibernate中默认的CacheProv ...
- 缓存机制总结(JVM内置缓存机制,MyBatis和Hibernate缓存机制,Redis缓存)
一.JVM内置缓存(值存放在JVM缓存中) 我们可以先了解一下Cookie,Session,和Cache Cookie:当你在浏览网站的时候,WEB 服务器会先送一小小资料放在你的计算机上,Cooki ...
- org.hibernate.exception.SQLGrammarException: could not execute query
SSH项目中出现了 org.hibernate.exception.SQLGrammarException: could not execute query 错误,仔细检查后发现,是把createQu ...
- hibernate学习(5)——对象状态与一级缓存
1.对象状态 1.1 状态介绍 hibernate 规定三种状态:瞬时态.持久态.脱管态 瞬时态:transient,session没有缓存对象,数据库也没有对应记录.没有与hibernate关联 ...
- org.hibernate.exception.JDBCConnectionException: could not execute query
最近在做一个项目,测试的时候是没有问题的,但是放到服务器上以后,第二天就会出现下面的异常.重启Tomcat服务器后就正常了,但是下一天还是会出现同样的异常..... 我就查了一些资料最终把问题给解决了 ...
- Android二级缓存之物理存储介质上的缓存DiskLruCache
Android二级缓存之物理存储介质上的缓存DiskLruCache Android DiskLruCache属于物理性质的缓存,相较于LruCache缓存,则DiskLruCache属于And ...
随机推荐
- linux kill 关闭进程命令
杀死进程最安全的方法是单纯使用kill命令,不加修饰符,不带标志. 首先使用ps -ef命令确定要杀死进程的PID,然后输入以下命令: # kill -pid 注释:标准的kill命令通常都能达到目的 ...
- [svc]tomcat配置文件详解
Tomcat系列之服务器的安装与配置以及各组件详解 tomcat 配置文件详解 tomcat安全管理规范
- location 将跟目录下某个文件夹指向2级目录
例如: /caffespressos/指向/web01/caffe/ [root@web01 default]# tree web01/ web01/ └── caffe └── index.html ...
- 怎么使用Less/Sass编译工具koala
怎么使用Less/Sass编译工具koala 如何使用Less/Sass编译工具koala 一.SASS调试插件的方法 如需调试功能,请在编译输出的时候输出debug信息,那样解析的css文件中就会包 ...
- Extjs GridPanel 中放入 Combox显示问题
http://weijun8611-126-com.iteye.com/blog/566201 在项目中使用了extjs的editorgridpanel,但是其中的combobox在选择了相应的选项后 ...
- RabbitMQ之HelloWorld【译】
简介 RabbitMQ是一个消息代理,主要的想法很简单:它接收并转发消息.你可以把它当做一个邮局,当你发送邮件到邮筒,你相信邮差先生最终会将邮件投递给收件人.RabbitMQ在这个比喻里,是一个邮筒, ...
- Amazon EC2云端服务器的使用方法
Amazon的EC2服务器可以理解为虚拟机,不过它是不需要安装系统的,它是根据镜像自动创建的.在申请EC2的时候,可以选择操作系统的类型,如Redhat Enterprise 6或ubuntu 12等 ...
- Linux - 用户管理常用命令
1.查看Linux已经存在的用户: [root@CMCC_91 ~]# cut -d : -f 1 /etc/passwd [root@CMCC_91 ~]# cat /etc/passwd |awk ...
- 第二百七十二节,Tornado框架-iframe标签框架伪造ajax
Tornado框架-iframe标签框架伪造ajax html <!DOCTYPE html> <html> <head lang="en"> ...
- Modify the server ports
在eclipse中配置好tomcat后,如今有需求须要在一个eclipse启动两个tomcat甚至很多其它,仅仅改动tomcat的8080port肯定不行的,详细须要改动tomcat的shutdown ...