Hibernate的二级缓存


1.1 Hibernate的二级缓存 :
Hibernate缓存分类:
一、 Session缓存(又称作事务缓存):Hibernate内置的,不能卸除。
缓存范围:缓存只能被当前Session对象访问。缓存的生命周期依赖于Session的生命周期,当Session被关闭后,缓存也就结束生命周期。
二、 SessionFactory缓存(又称作应用缓存):使用第三方插件,可插拔。
缓存范围:缓存被应用范围内的所有session共享,不同的Session可以共享。这些session有可能是并发访问缓存,因此必须对缓存进行更新。缓存的生命周期依赖于应用的生命周期,应用结束时,缓存也就结束了生命周期,二级缓存存在于应用程序范围。

二级缓存的配置
*在Hibernate中开启二级缓存
*配置二级缓存的提供商:
*Ehcache
*配置哪些类使用二级缓存
*在映射文件中配置
*在核心配置文件中配置(推荐)



1.1.1 类缓存区特点:
缓存的是对象的 散装的数据.

只发送一次SQL,而且customer1==customer2,customer3==customer4

1.1.2 集合缓存区的特点:
缓存的是对象的 id.需要 依赖类缓冲区的配置.

1.1.3 二级缓存list和iterate的区别:
*list()方法发送一条sql查询所有数据,但是iterate()方法会发送1+N条SQL查询数据
*list不能使用二级缓存,但是 iterate可以使用二级缓存,利用二级缓存只需要发送1条SQL,N条不再需要发送
//测试二级缓存-list
@Test
public void test5() {
Session session = HibernateUtils.openSessioin();
Transaction tx = session.beginTransaction();
List<Customer3> list1 = session.createQuery("from Customer3").list();
System.out.println(list1.toString());
tx.commit();
session = HibernateUtils.openSessioin();
tx = session.beginTransaction();
List<Customer3> list2 = session.createQuery("from Customer3").list();
System.out.println(list2.toString());
tx.commit();
}
//下面可发现发送了两次的SQL
Hibernate:
select
customer3x0_.cid as cid5_,
customer3x0_.ver as ver5_,
customer3x0_.cname as cname5_
from
customer3 customer3x0_
[Customer3 [cid=1, cname=何泳锋, version=1], Customer3 [cid=2, cname=冯瑶, version=1], Customer3 [cid=3, cname=哈哈, version=1]]
Hibernate:
select
customer3x0_.cid as cid5_,
customer3x0_.ver as ver5_,
customer3x0_.cname as cname5_
from
customer3 customer3x0_
[Customer3 [cid=1, cname=何泳锋, version=1], Customer3 [cid=2, cname=冯瑶, version=1], Customer3 [cid=3, cname=哈哈, version=1]]

//测试二级缓存-iterate
@Test
public void test5() {
Session session = HibernateUtils.openSessioin();
Transaction tx = session.beginTransaction();
Iterator<Customer3> iterator1= session.createQuery("from Customer3").iterate();
while (iterator1.hasNext()) {
System.out.println(iterator1.next());
}
tx.commit();
session = HibernateUtils.openSessioin();
tx = session.beginTransaction();
Iterator<Customer3> iterator2= session.createQuery("from Customer3").iterate();
while (iterator2.hasNext()) {
System.out.println(iterator2.next());
}
tx.commit();
}
//第一次session发送1+N条记录
//这是1
Hibernate:
select
customer3x0_.cid as col_0_0_
from
customer3 customer3x0_
//下面是N
Hibernate:
select
customer3x0_.cid as cid5_0_,
customer3x0_.ver as ver5_0_,
customer3x0_.cname as cname5_0_
from
customer3 customer3x0_
where
customer3x0_.cid=?
Customer3 [cid=1, cname=何泳锋, version=1]
Hibernate:
select
customer3x0_.cid as cid5_0_,
customer3x0_.ver as ver5_0_,
customer3x0_.cname as cname5_0_
from
customer3 customer3x0_
where
customer3x0_.cid=?
Customer3 [cid=2, cname=冯瑶, version=1]
Hibernate:
select
customer3x0_.cid as cid5_0_,
customer3x0_.ver as ver5_0_,
customer3x0_.cname as cname5_0_
from
customer3 customer3x0_
where
customer3x0_.cid=?
Customer3 [cid=3, cname=哈哈, version=1]
//第二次session,只发送了1,不用发送N,因为利用了二级缓存
Hibernate:
select
customer3x0_.cid as col_0_0_
from
customer3 customer3x0_
Customer3 [cid=1, cname=何泳锋, version=1]
Customer3 [cid=2, cname=冯瑶, version=1]
Customer3 [cid=3, cname=哈哈, version=1]


1.1.4 一级缓存数据更新会同步到二级缓存:
//测试一级缓存更新到二级缓存
@Test
public void test6() {
Session session = HibernateUtils.openSessioin();
Transaction tx = session.beginTransaction();
Customer3 customer =(Customer3) session.get(Customer3.class, 1);
customer.setCname("泳锋");
//利用一级缓存,发送SQL自动更新数据
tx.commit();
session = HibernateUtils.openSessioin();
tx = session.beginTransaction();
//不会再发送SQL进行查询,而且查询的是更新后的数据
Customer3 customer1 = (Customer3) session.get(Customer3.class,1);
System.out.println(customer1);
tx.commit();
}
//第一个session查询客户信息
Hibernate:
select
customer3x0_.cid as cid5_0_,
customer3x0_.ver as ver5_0_,
customer3x0_.cname as cname5_0_
from
customer3 customer3x0_
where
customer3x0_.cid=?
//第一个tx提交事务时,一级缓存自动发送SQL更新数据
Hibernate:
update
customer3
set
ver=?,
cname=?
where
cid=?
and ver=?
//第二个session再查询同一个客户的时,不用发送SQL,而且时最新的记录
Customer3 [cid=1, cname=何泳锋, version=3]

1.1.5 二级缓存数据到硬盘:
*导入对应需要的jar包
backport-util-concurrent.jar
commons-logging.jar
ehcache-1.5.0.jar

*添加ehcache.xml文件 当内存中的数据量超过了设置的最大记录数maxElementsInMemory,则会将多余的记录数存入硬盘,但是内存中已经存在的内容则不会自动存入硬盘,需要手动使用cache.flush()来强制将内存内容放入硬盘中;
一般maxElementsOnDisk的值需要设置的比maxElementsInMemory大,这样效率会高一些;
需要设置overflowToDisk为true,表示使用硬盘缓存策略;
需要设置diskPersistent为true,否则重启服务后缓存文件会被清理掉,同时该属性会在一定程度上拖慢缓存速度,因为它需要不停地监控设置的硬盘大小是否已满关联属性为diskSpoolBufferSizeMB,如果硬盘够大可以将该属性设置足够大;
最后 会生成*.index和*.data2个文件;

*重建缓存会自动从硬盘读取数据到内存

diskStore :指定数据存储位置,可指定磁盘中的文件夹位置
maxElementsInMemory: 在内存中缓存的element的最大数目。
maxElementsOnDisk: 在磁盘上缓存的element的最大数目,默认值为0,表示不限制。 
eternal: 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断。
overflowToDisk: 如果内存中数据超过内存限制,是否要缓存到磁盘上。

以下属性是可选的: 
timeToIdleSeconds: 对象空闲时间,指对象在多长时间没有被访问就会失效。只对eternal为false的有效。默认值0,表示一直可以访问。
timeToLiveSeconds: 对象存活时间,指对象从创建到失效所需要的时间。只对eternal为false的有效。默认值0,表示一直可以访问。
diskPersistent: 是否在磁盘上持久化。指重启jvm后,数据是否有效。默认为false。 
diskExpiryThreadIntervalSeconds: 对象检测线程运行时间间隔。标识对象状态的线程多长时间运行一次。 
diskSpoolBufferSizeMB: DiskStore使用的磁盘大小,默认值30MB。每个cache使用各自的DiskStore。
memoryStoreEvictionPolicy: 如果内存中数据超过内存限制,向磁盘缓存时的策略。默认值LRU,可选FIFO、LFU。


1.1.5.1 编码测试-存数据:



1.1.5.1 编码测试-取数据: 
取出上面存的数据:有1-Customer3,2-Customer3
1.1.6 更新时间戳区域:
 
1.1.7 查询缓存:
比二级缓存功能更加强大,而且 查询缓存必须依赖二级缓存.
二级缓存:对 类/对象的缓存.
查询缓存:针对类中属性的缓存.
//这个二级缓存是不能缓存的,不过设置了查询缓存就可以在查询缓存里面缓存了
Query query=session.createQuery("select c.cname from Customer");
*hibernate.hbm.xml文件中添加
*代码(这样第二次就不会再发送SQL语句了)

查询缓存的配置:
* 配置查询缓存:
* 前提是二级缓存已经配置完毕.
* 在核心配置文件中:
<!-- 配置查询缓存 -->
<property name="hibernate.cache.use_query_cache">true</property>
* 编写代码的时候:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值