MyBatis--03-- 一级缓存和二级缓存

什么叫缓存

  • 将数据存放在程序内存中,用于减轻数据查询的压力,提升读取数据的速度,提高性能。

  • 对于任何一个持久层框架,都有缓存机制;缓存在电脑中有一块真实的存储空间

Mybatis缓存

mybaits提供一级缓存,和二级缓存。

  • 一级缓存(本地缓存)
    sqlSession级别的缓存。(相当于一个方法内的缓存)
  • 二级缓存(全局缓存)
    基于namespace名称空间级别的缓存.即一个mapper.xml对应一个缓存

MyBatis--03-- 一级缓存和二级缓存_第1张图片
MyBatis--03-- 一级缓存和二级缓存_第2张图片
MyBatis--03-- 一级缓存和二级缓存_第3张图片

一级缓存(本地缓存)

一级缓存基于sqlSession默认开启,在操作数据库时需要构造SqlSession对象,在对象中有一个HashMap用于存储缓存数据。不同的SqlSession之间的缓存数据区域是互相不影响的。

一级缓存的作用域是SqlSession范围的,当在同一个sqlSession中执行两次相同的sql语句时,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次查询时会从缓存中获取数据,不再去底层数据库查询,从而提高查询效率。

Mybatis的内部缓存使用一个HashMap,key为hashcode+statementId+sql语句。Value为查询出来的结果集映射成的java对象。
SqlSession执行insert、update、delete等操作commit后会清空该SQLSession缓存

需要注意的是,如果SqlSession执行了DML操作(增删改),并且提交到数据库,MyBatis则会清空SqlSession中的一级缓存,这样做的目的是为了保证缓存中存储的是最新的信息,避免出现脏读现象。

当一个SqlSession结束后该SqlSession中的一级缓存也就不存在了。

关闭一级缓存后,再次访问,需要再次获取一级缓存,然后才能查找数据,否则会抛出异常。

案例:

MyBatis--03-- 一级缓存和二级缓存_第4张图片
第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息。得到用户信息,将用户信息存储到一级缓存中。

如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。

第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。

二级缓存(全局缓存)

Mybatis的二级缓存是指mapper映射文件。二级缓存的作用域是同一个namespace下的mapper映射文件内容,多个SqlSession共享。

Mybatis需要手动设置启动二级缓存。

二级缓存的作用域是mapper的同一个namespace。不同的sqlSession两次执行相同的namespace下的sql语句,且向sql中传递的参数也相同,即最终执行相同的sql语句,则第一次执行完毕会将数据库中查询的数据写到缓存,第二次查询会从缓存中获取数据,不再去底层数据库查询,从而提高效率。

案例:

  1. 基于namespace名称空间级别的缓存:一个namespace对应一个二级缓存即一个mapper.xml对应一个缓存:

MyBatis--03-- 一级缓存和二级缓存_第5张图片

1、工作机制:

  1. 一个会话,查询一条数据,这个数据就会被放在当前会话的一级缓存中;
  2. 如果会话关闭;一级缓存中的数据会被保存到二级缓存中;新的会话查询信息,就可以参照二级缓存中的内容;
  3. sqlSession=EmployeeMapper>Employee
    DepartmentMapper===>Department
    不同namespace查出的数据会放在自己对应的缓存中(map)
    效果:数据会从二级缓存中获取
    查出的数据都会被默认先放在一级缓存中。
    只有会话提交或者关闭以后,一级缓存中的数据才会转移到二级缓存中

2、 使用:

1)、开启全局二级缓存配置:
2)、去mapper.xml中配置使用二级缓存:
< cache>< /cache>
3)、我们的POJO需要实现序列化接口

1)在mybatis全局配置文件中开启全局二级缓存配置:< setting name=“cacheEnabled” value=“true”/>

MyBatis--03-- 一级缓存和二级缓存_第6张图片
2)在mapper.xml中配置使用二级缓存

直接加上: < cache>

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.mybatis.dao.EmployeeMapper">
	
	 <cache><cache/>
 
 	<!--public Map<Integer, Employee> getEmpByLastNameLikeReturnMap(String lastName);  -->
 	<select id="getEmpByLastNameLikeReturnMap" resultType="com.atguigu.mybatis.bean.Employee">
 		select * from tbl_employee where last_name like #{lastName}
 	</select>
</mapper>

中配置一些参数:

eviction:缓存的回收策略:

• LRU – 最近最少使用的:移除最长时间不被使用的对象。
• FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
• SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
• WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
• 默认的是 LRU。
  • evicition收回策略,默认是LRU

(1)LRU最近最少使用策略,一处做长时间不被使用的对象。
(2)FIFO先进先出策略,按对象进入缓存的顺序来移除它们。
(3)SOFT软引用策略,移除基于垃圾回收器状态和软引用规则的对象。
(4)WEAK弱引用策略,更积极地移除基于垃圾收集器状态和弱引用规则的对象

flushInterval:缓存刷新间隔

缓存多长时间清空一次,默认不清空,设置一个毫秒值

readOnly:是否只读:

  • true:只读;mybatis认为所有从缓存中获取数据的操作都是只读操作,不会修改数据。
    mybatis为了加快获取速度,直接就会将数据在缓存中的引用交给用户。不安全,速度快

  • false:非只读:mybatis觉得获取的数据可能会被修改。
    mybatis会利用序列化&反序列的技术克隆一份新的数据给你。安全,速度慢

size:

缓存存放多少元素;

type=“”:

指定自定义缓存的全类名;
实现Cache接口即可;

MyBatis--03-- 一级缓存和二级缓存_第7张图片

缓存的顺序:

  1. 二级缓存
  2. 一级缓存
  3. 数据库

二级缓存的使用原则

  1. 只能在一个命名空间下使用二级缓存
    由于二级缓存中的数据是基于namespace的,即不同namespace中的数据互不干扰。在多个namespace中若均存在对同一个表的操作,那么这多个namespace中的数据可能就会出现不一致现象。

  2. 在单表上使用二级缓存
    如果一个表与其它表有关联关系,那么久非常有可能存在多个namespace对同一数据的操作。而不同namespace中的数据互补干扰,所以就有可能出现多个namespace中的数据不一致现象。

  3. 查询多于修改时使用二级缓存
    在查询操作远远多于增删改操作的情况下可以使用二级缓存。因为任何增删改操作都将刷新二级缓存,对二级缓存的频繁刷新将降低系统性能

你可能感兴趣的:(Spring基础知识--SSM,mybatis,缓存,spring)