Mybatis缓存

测试结果: 一级缓存中的数据没有了,重新查数据库


3. 对SqlSession执行更新操作(update、delete、insert)时,同时不调用SqlSession.commit或SqlSession.close(),这时只会清空其自身的一级缓存,对二级缓存没有影响。 

测试:

结果:


4. 对SqlSession执行更新操作(update、delete、insert)后并执行SqlSession.commit()时,不仅清空其自身的一级缓存(执行更新操作的结果),也清空二级缓存(执行commit()的效果)。 

测试:

结果:


5. 对SqlSession执行更新操作(update、delete、insert)后并执行SqlSession.close()时(没有执行SqlSession.commit()),需分两类情况。当autoCommit为false时,只会清空其自身的一级缓存(执行更新操作的效果),对二级缓存没有影响。当autoCommit为true时,会清空二级缓存。 

测试:自动提交为false

结果:

测试:自动提交为true

1、缓存

为了减轻数据库的访问压力,mybatis提供了缓存功能,如果命中缓存将直接返回缓存中的结果实例,不再需要查询数据库

1.1一级缓存

一级缓存也叫本地缓存,它默认会启用,并且不能关闭.一级缓存存在于SqlSession的生命周期中,即它是SqlSession级别的缓存。在同一个 SqlSession中查询时,MyBatis会把执行的方法和参数通过算法生成缓存的键值,将键值和查询结果存入一个Map对象中.如果同一个SqlSession 中执行的方法和参数完全一致,那么通过算法会生成相同的键值,当Map缓存对象中己经存在该键值时,则会返回缓存中的对象。

编写SQL映射文件:

测试一级缓存: 在同一个SqlSession中进行查询操作

测试结果:仅仅创建了一个数据库连接,发送了一次SQL,缓存起到效果

1.2 二级缓存

二级缓存也叫为全局缓存,是SqlSessionFactory 映射级别的缓存,二级缓存存在于SqlSessionFactory的生命周期中,即它是SqlSessionFactory级别的缓存。在多个 SqlSession 之间共享缓存数据。

1、在 MyBatis 的全局配置文件(mybatis-config.xml)中,添加如下配置:

2、在需要进行二级缓存的 Mapper XML 文件中,添加如下配置:

这将启用该 Mapper 的二级缓存功能

3.进行缓存的对象需要实现序列化接口

4.使用二级缓存,在 Mapper 的 SQL 语句中,使用 useCache 属性来指定是否使用二级缓存。例如:

useCache="true" 表示使用二级缓存。如果查询结果已经在缓存中存在,则直接返回缓存结果,否则查询数据库并将结果存入缓存。

5.测试二级缓存,此时需要使用同一个SqlSessionFactory创建不同的SqlSession

测试结果: 缓存命中率为0.5,通过缓存获取数据

1.3查询顺序

1、先判断二级缓存是否开启,如果没开启,再判断一级缓存是否开启,如果没开启,直接查数据库

2、如果一级缓存关闭,即使二级缓存开启也没有数据,因为二级缓存的数据从一级缓存获取

3、一般不会关闭一级缓存

4、二级缓存默认不开启

5、如果二级缓存关闭,直接判断一级缓存是否有数据,如果没有就查数据库

6、如果二级缓存开启,先判断二级缓存有没有数据,如果有就直接返回;如果没有,就查询一级缓存,如果有就返回,没有就查询数据库;

测试数据1:

测试结果1:

测试数据2:

测试结果2:

两次打印中,第二次还去查了二级缓存;说明当二级缓存开启的情况下,即使是一个sqlSession中的缓存,都会先去查一下二级缓存,再返回查一级缓存; 所以说,缓存执行顺序是:二级缓存-->一级缓存-->数据库

1.4缓存总结[close方法和commit方法对缓存的影响]

1. 进行select操作后,调用SqlSession.close()方法,会将其一级缓存的数据放进二级缓存中,此时一级缓存随着SqlSession的关闭也就不存在了。 

2. 进行select操作后,调用SqlSession.commit()方法,会将其一级缓存的数据放进二级缓存中,并清空一级缓存。 

测试:关闭二级缓存

测试结果: 一级缓存中的数据没有了,重新查数据库


3. 对SqlSession执行更新操作(update、delete、insert)时,同时不调用SqlSession.commit或SqlSession.close(),这时只会清空其自身的一级缓存,对二级缓存没有影响。 

测试:

结果:


4. 对SqlSession执行更新操作(update、delete、insert)后并执行SqlSession.commit()时,不仅清空其自身的一级缓存(执行更新操作的结果),也清空二级缓存(执行commit()的效果)。 

测试:

结果:


5. 对SqlSession执行更新操作(update、delete、insert)后并执行SqlSession.close()时(没有执行SqlSession.commit()),需分两类情况。当autoCommit为false时,只会清空其自身的一级缓存(执行更新操作的效果),对二级缓存没有影响。当autoCommit为true时,会清空二级缓存。 

测试:自动提交为false

结果:

测试:自动提交为true

1.5回收策略

MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。MyBatis 3 中的缓存实现的很多改进都已经实现了,使得它更加强大而且易于配置。

默认情况下是没有开启缓存的,除了局部的 session 缓存,可以增强变现而且处理循环 依赖也是必须的。要开启二级缓存,你需要在你的 SQL 映射文件中添加一行: <cache/>字面上看就是这样。这个简单语句的效果如下: 

映射语句文件中的所有 select 语句将会被缓存。 

映射语句文件中的所有 insert,update 和 delete 语句会刷新缓存。

缓存会使用 Least Recently Used(LRU,最近最少使用的)算法来收回。 

根据时间表(比如 no Flush Interval,没有刷新间隔),缓存不会以任何时间顺序 来刷新。 

缓存会存储列表集合或对象(无论查询方法返回什么)的 1024 个引用。 

缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,而且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

所有的这些属性都可以通过缓存元素的属性来修改。

比如:这个更高级的配置创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会导致冲突。

可用的收回策略有:

LRU – 最近最少使用的:移除最长时间不被使用的对象。 

FIFO – 先进先出:按对象进入缓存的顺序来移除它们。 

SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。 

WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。 默认的是 LRU。

flushInterval(刷新间隔)可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。

size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的可用内存资源数目。默认值是 1024。

readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是 false。

  • 33
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值