1. 什么是缓存?

数据库的缓存指的是应用程序和物理数据源之间的数据。即把物理数据源的数据复制到缓存。有了缓存,可以降低应用程序对物理数据源的访问频率,从而提高效率。缓存的介质一般是内存,也可以是硬盘。
Hibernate的缓存有三种类型:一级缓存、二级缓存和查询缓存。
2. 一级缓存
一级缓存即Session缓存,由Session自动进行管理,不需要程序进行干预。一级缓存根据对象的ID进行加载和缓存。如下面的代码:
@Override
public void testCache() {
// TODO Auto-generated method stub
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Course c = (Course) session.get(Course.class, 1);
System.out.println("Name:" + c.getName());
c = (Course) session.get(Course.class, 1);
System.out.println("Name:" + c.getName());
tx.commit();
session.close();
}
运行结果:
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
Name:计算机原理
Name:计算机原理
第1次查询时生成了SQL语句,并将查询出来的对象放在一级缓存里面,第2次查询时,在一级缓存里面直接找到了这个对象,就不需要再次生成SQL语句了。
再看一个例子:
@Override
public void testCache() {
// TODO Auto-generated method stub
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Course c = (Course) session.get(Course.class, 1);
System.out.println("Name:" + c.getName());
tx.commit();
session.close();
session = sessionFactory.openSession();
tx = session.beginTransaction();
c = (Course) session.get(Course.class, 1);
System.out.println("Name:" + c.getName());
tx.commit();
session.close();
}
由于一级缓存是Session级别的缓存,所以Session关闭以后,一级缓存也就不存在了,第2次查询也要生成SQL语句:
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
Name:计算机原理
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
Name:计算机原理
3. 二级缓存
二级缓存即SessionFactory缓存,和一级缓存类似,也是根据对象的ID进行加载和缓存,区别就在于一级缓存只在Session内有效,而二级缓存在SessionFactory内有效。在访问某个ID的对象时,先到一级缓存里面去找,如果没有找到就到二级缓存里面去找。二级缓存包括EHCache,OSCache,SwarmCache和JBossCache等。这里以EHCache作为例子。
二级缓存需要程序进行管理。首先,配置Maven下载相关的Jar,在pom文件里面添加:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>4.1.0.Final</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.8.3</version>
</dependency>
创建EHCache配置文件ehcache.xml:
<ehcache>
<diskStore path="E:\Eclipse\MyWorkspace\Cache"/>
<defaultCache
maxElementsInMemory="10000"
eternal="true"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
<cache name="com.hzhi.course.entity.Course"
maxElementsInMemory="10000"
eternal="true"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
</ehcache>
defaultCache是默认的设置,下面一个cache指明了对哪一个类进行二级缓存。里面设置了最大缓存的对象数量,是否永久有效、最大空闲秒数、最大生存秒数、内存满时是否写到硬盘,写到硬盘的路径等等。
修改需要缓存的类的hbm文件:
<class name="com.hzhi.course.entity.Course" table="clas">
<cache usage="read-only"/>
......
</class>
usage设置了并发访问策略,一般设置成read-only。
修改applicationContext.xml中的SessionFactory的配置,增加二级缓存的一些属性:
<!-- SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" >
<ref local="dataSource"/>
</property>
<!-- 配置Hibernate的属性 -->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.connection.isolation">8</prop>
<!-- 二级缓存 -->
<prop key="hibernate.cache.use_second_level_cache">false</prop>
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
<prop key="hibernate.cache.provider_configuration_file_resource_path">WEB-INF/ehcache.xml</prop>
</props>
</property>
......
</bean>
运行下面的例子:
@Override
public void testCache() {
// TODO Auto-generated method stub
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Course c = (Course) session.get(Course.class, 1);
System.out.println("Name:" + c.getName());
tx.commit();
session.close();
session = sessionFactory.openSession();
tx = session.beginTransaction();
c = (Course) session.get(Course.class, 1);
System.out.println("Name:" + c.getName());
tx.commit();
session.close();
}
结果:
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
Name:计算机原理
Name:计算机原理
虽然关闭了Session,但是二级缓存仍然存在,所以只生成了一次SQL语句。
下面的例子:
@Override
public void testCache() {
// TODO Auto-generated method stub
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery("from Course");
Iterator iter = query.iterate();
while(iter.hasNext()){
System.out.println(((Course)iter.next()).getName());
}
tx.commit();
session.close();
session = sessionFactory.openSession();
tx = session.beginTransaction();
query = session.createQuery("from Course");
iter = query.iterate();
while(iter.hasNext()){
System.out.println(((Course)iter.next()).getName());
}
tx.commit();
session.close();
}
结果:
Hibernate:
select
course0_.ID as col_0_0_
from
clas course0_
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
计算机原理
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
计算机网络
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
数据库原理
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
C语言
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
大学英语A
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
Java
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
Linux
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
高等数学
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
语文
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
大学物理
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
软件工程
Hibernate:
select
course0_.ID as col_0_0_
from
clas course0_
计算机原理
计算机网络
数据库原理
C语言
大学英语A
Java
Linux
高等数学
语文
大学物理
软件工程
当使用Query的list()方法时,只生成一次SQL语句查询出所有的对象,使用iterate()方法时,会先得到所有对象的ID,然后根据每个ID生成一次SQL语句查询。第二个Session里面使用的也是iterate()方法,首先生成一次SQL语句,得到ID,然后根据ID查找对象,由于开启了二级缓存,在二级缓存里面找到了对象,所以就直接输出了,并没有再根据每个ID生成SQL语句。
不论是一级缓存还是二级缓存,都只能缓存对象,不能缓存属性的值。下面的例子:
@Override
public void testCache() {
// TODO Auto-generated method stub
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery("select c.name from Course c");
List<String> names = query.list();
for(Iterator iter = names.iterator(); iter.hasNext();){
String name = (String) iter.next();
System.out.println(name);
}
System.out.println("----------");
query = session.createQuery("select c.name from Course c");
names = query.list();
for(Iterator iter = names.iterator(); iter.hasNext();){
String name = (String) iter.next();
System.out.println(name);
}
System.out.println("----------");
tx.commit();
session.close();
}
运行结果:
Hibernate:
select
course0_.NAME as col_0_0_
from
clas course0_
计算机原理
计算机网络
数据库原理
C语言
大学英语A
Java
Linux
高等数学
语文
大学物理
软件工程
----------
Hibernate:
select
course0_.NAME as col_0_0_
from
clas course0_
计算机原理
计算机网络
数据库原理
C语言
大学英语A
Java
Linux
高等数学
语文
大学物理
软件工程
----------
虽然开启了二级缓存,但是查询的结果不是对象,是属性,所以并没有缓存,第2次查询仍然生成了查询语句。要解决这个问题,就需要查询缓存。
3. 查询缓存
在配置了二级缓存的基础上,可以设置查询缓存,在SessionFactory的设置里面加上一行:
<prop key="hibernate.cache.use_query_cache">true</prop>
即打开了查询缓存。查询缓存也是SessionFactory级别的缓存,在整个SessionFactory里面都是有效的。
关闭二级缓存,运行下面的例子,在Query后面添加setCacheable(true)打开查询缓存:
@Override
public void testCache() {
// TODO Auto-generated method stub
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery("select c.name from Course c");
query.setCacheable(true);
List<String> names = query.list();
for(Iterator iter = names.iterator(); iter.hasNext();){
String name = (String) iter.next();
System.out.println(name);
}
System.out.println("----------");
query = session.createQuery("select c.name from Course c");
query.setCacheable(true);
names = query.list();
for(Iterator iter = names.iterator(); iter.hasNext();){
String name = (String) iter.next();
System.out.println(name);
}
System.out.println("----------");
tx.commit();
session.close();
}
结果:
Hibernate:
select
course0_.NAME as col_0_0_
from
clas course0_
计算机原理
计算机网络
数据库原理
C语言
大学英语A
Java
Linux
高等数学
语文
大学物理
软件工程
----------
计算机原理
计算机网络
数据库原理
C语言
大学英语A
Java
Linux
高等数学
语文
大学物理
软件工程
----------
由于两次查询的HQL语句是一致的,所以只生成一次SQL语句。但是如果把第二次查询改一下:
System.out.println("----------");
query = session.createQuery("select c.name from Course c where c.id > 5");
query.setCacheable(true);
names = query.list();
for(Iterator iter = names.iterator(); iter.hasNext();){
String name = (String) iter.next();
System.out.println(name);
}
System.out.println("----------");
结果:
Hibernate:
select
course0_.NAME as col_0_0_
from
clas course0_
计算机原理
计算机网络
数据库原理
C语言
大学英语A
Java
Linux
高等数学
语文
大学物理
软件工程
----------
Hibernate:
select
course0_.NAME as col_0_0_
from
clas course0_
where
course0_.ID>5
大学英语A
Java
Linux
高等数学
语文
大学物理
软件工程
----------
由于HQL语句变了,所以第二次也生成了SQL语句。
查询缓存可以缓存属性,也可以缓存对象,但是当缓存对象时,只缓存对象的ID,不会缓存整个对象。下面的例子:
@Override
public void testCache() {
// TODO Auto-generated method stub
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery("from Course");
query.setCacheable(true);
List<Course> list = query.list();
for (int i=0; i<list.size(); i++){
System.out.println(list.get(i).getName());
}
System.out.println("----------");
tx.commit();
session.close();
session = sessionFactory.openSession();
tx = session.beginTransaction();
query = session.createQuery("from Course");
query.setCacheable(true);
list = query.list();
for (int i=0; i<list.size(); i++){
System.out.println(list.get(i).getName());
}
System.out.println("----------");
tx.commit();
session.close();
}
结果:
Hibernate:
select
course0_.ID as ID0_,
course0_.NAME as NAME0_,
course0_.COMMENT as COMMENT0_
from
clas course0_
计算机原理
计算机网络
数据库原理
C语言
大学英语A
Java
Linux
高等数学
语文
大学物理
软件工程
----------
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
Hibernate:
select
course0_.ID as ID0_0_,
course0_.NAME as NAME0_0_,
course0_.COMMENT as COMMENT0_0_
from
clas course0_
where
course0_.ID=?
计算机原理
计算机网络
数据库原理
C语言
大学英语A
Java
Linux
高等数学
语文
大学物理
软件工程
----------
由于开了查询缓存,没有开二级缓存,虽然使用的是list()方法一次查询出了所有的对象,但是查询缓存只缓存了对象ID,没有缓存整个对象。所以在第2个Session里面"from Course"这个HQL由于和前面的相同,并没有生成SQL语句,但是由于没有开二级缓存,没有缓存整个对象,只能根据每个ID去生成一次SQL语句。虽然两次用的都是list()方法,但是第一次是生成SQL语句去一次查询出所有的对象,而第二次是根据查询缓存里面的ID一个一个的生成SQL语句。
如果同时打开查询缓存和二级缓存,第2个Session里面就不用再根据ID去生成SQL语句了:
Hibernate:
select
course0_.ID as ID0_,
course0_.NAME as NAME0_,
course0_.COMMENT as COMMENT0_
from
clas course0_
计算机原理
计算机网络
数据库原理
C语言
大学英语A
Java
Linux
高等数学
语文
大学物理
软件工程
----------
计算机原理
计算机网络
数据库原理
C语言
大学英语A
Java
Linux
高等数学
语文
大学物理
软件工程
----------
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!
# Hibernate
# 缓存
# 详解Java的Hibernate框架中的缓存与二级缓存
# 详解Java的Hibernate框架中的缓存与原生SQL语句的使用
# 详解Java的Hibernate框架中的注解与缓存
# 浅析Java的Hibernate框架中的缓存和延迟加载机制
# java模拟hibernate一级缓存示例分享
# Hibernate框架中的缓存技术详解
# SSH框架网上商城项目第16战之Hibernate二级缓存处理首页热门显示
# Spring 整合 Hibernate 时启用二级缓存实例详解
# 详解Hibernate缓存与性能优化
# 软件工程
# 大学英语
# 都是
# 两次
# 去找
# 写到
# 应用程序
# 的是
# 找到了
# 加载
# 内有效
# 放在
# 出了
# 也就
# 也要
# 不需要
# 就不
# 基础上
# 开了
# 第二个
相关文章:
建站之星如何一键生成手机站?
昆明高端网站制作公司,昆明公租房申请网上登录入口?
在线ppt制作网站有哪些软件,如何把网页的内容做成ppt?
保定网站制作方案定制,保定招聘的渠道有哪些?找工作的人一般都去哪里看招聘信息?
建站之星后台搭建步骤解析:模板选择与产品管理实操指南
如何快速搭建自助建站会员专属系统?
东莞专业制作网站的公司,东莞大学生网的网址是什么?
常州企业网站制作公司,全国继续教育网怎么登录?
建站之星如何实现PC+手机+微信网站五合一建站?
网站制作外包价格怎么算,招聘网站上写的“外包”是什么意思?
建站之星后台密码遗忘或太弱?如何重置与强化?
建站之星如何助力企业快速打造五合一网站?
如何在香港免费服务器上快速搭建网站?
三星网站视频制作教程下载,三星w23网页如何全屏?
家族网站制作贴纸教程视频,用豆子做粘帖画怎么制作?
高防服务器租用首荐平台,企业级优惠套餐快速部署
大型企业网站制作流程,做网站需要注册公司吗?
如何选择CMS系统实现快速建站与SEO优化?
建站org新手必看:2024最新搭建流程与模板选择技巧
安徽网站建设与外贸建站服务专业定制方案
高性能网站服务器部署指南:稳定运行与安全配置优化方案
全景视频制作网站有哪些,全景图怎么做成网页?
外贸公司网站制作,外贸网站建设一般有哪些步骤?
如何在IIS服务器上快速部署高效网站?
简单实现Android验证码
高防服务器租用指南:配置选择与快速部署攻略
无锡制作网站公司有哪些,无锡优八网络科技有限公司介绍?
html制作网站的步骤有哪些,iapp如何添加网页?
音乐网站服务器如何优化API响应速度?
专业商城网站制作公司有哪些,pi商城官网是哪个?
,在苏州找工作,上哪个网站比较好?
黑客如何通过漏洞一步步攻陷网站服务器?
建站之星代理如何优化在线客服效率?
高配服务器限时抢购:企业级配置与回收服务一站式优惠方案
建站之星导航如何优化提升用户体验?
如何快速搭建个人网站并优化SEO?
较简单的网站制作软件有哪些,手机版网页制作用什么软件?
如何选择适合PHP云建站的开源框架?
网页设计网站制作软件,microsoft office哪个可以创建网页?
简历在线制作网站免费版,如何创建个人简历?
在线ppt制作网站有哪些,请推荐几个好的课件下载的网站?
文字头像制作网站推荐软件,醒图能自动配文字吗?
如何通过西部数码建站助手快速创建专业网站?
如何正确下载安装西数主机建站助手?
杭州银行网站设计制作流程,杭州银行怎么开通认证方式?
如何在宝塔面板中创建新站点?
建站主机如何安装配置?新手必看操作指南
如何在Windows虚拟主机上快速搭建网站?
如何配置IIS站点权限与局域网访问?
上海制作企业网站有哪些,上海有哪些网站可以让企业免费发布招聘信息?
*请认真填写需求信息,我们会在24小时内与您取得联系。