【mybatis缓存机制】

一、mybatis缓存介绍

在mybatis框架中存在有缓存数据功能。
mybatis中缓存区域分为一级缓存和二级缓存,如下图:
在这里插入图片描述
mybatis中,一级缓存的作用域在一个sqlsession中,在同一个sqlsession中执行两个相同的sql语句,第一次执行的sql语句后的结果数据将会写入到缓存中,第二次执行时就不会再去数据库中查询,直接会去缓存中获取,从而提高查询效率。当一个sqlsession结束后该sqlsession中的一级缓存就不存在了。mybatis默认开启一级缓存。
mybatis的二级缓存是多个sqlsession共享的,它的作用于是mapper的同一个namespace,不同的sqlsession执行相同namespace下的sql语句且向sql语句中传递的参数也相同。即最终执行相同的sql语句,第一次会将执行的结果写入二级缓存中,第二次执行相同的sql时不会再去数据库查询,直接从缓存中取数据,从而提升了查询效率。mybatis默认没有开启二级缓存,需要在setting全局参数中配置开启二级缓存。

在主配置文件中添加以下配置

<settings>
    <setting name="cacheEnabled" value="true" />
</settings>

在需要开启二级缓存的mapper映射文件中添加以下代码(在 < mapper namespace>下方)

<cache />

二、一级缓存

1、原理

在这里插入图片描述

上图是查询id为1的用户图解,这整个就是一个sqlsession,一级缓存是根据sqlsession为单位来划分的。
每次查询都会先从缓存中查找,若没有才会到数据库中查找,查询到的数据再写入缓存中。
mybatis内部存储缓存使用一个hashmap,key为hashcode+sqlID+sql语句组成,value为从查询中映射出的java对象
sqlsession执行insert、update、delete登操作commit提交后会清空缓存区全部内容。

2、测试

//获取session
SqlSession session = sessionFactory.openSession();
//获限mapper接口实例
SysUserDao userMapper = session.getMapper(SysUserDao.class);
//第一次查询
SysUser user1 = userMapper.findUserById(1);
System.out.println(user1);
// 第二次查询,由于是同一个session则不再向数据发出语句直接从缓存取出
SysUser user2 = userMapper.findUserById(1);
System.out.println(user2);
// 关闭session
session.close();

执行后的结果地址相同,说明第一次的结果和第二次的结果在内存中是同一个。

edu.mybatis2.pojo.SysUser@6b9651f3
edu.mybatis2.pojo.SysUser@6b9651f3

执行第一次查询后执行添加操作,再执行第二次查询

//获取session
SqlSession session = sessionFactory.openSession();
//获限mapper接口实例
SysUserDao userMapper = session.getMapper(SysUserDao.class);
//第一次查询
SysUser user1 = userMapper.findUserById(1);
System.out.println(user1);
//添加一条数据
SysUser user = new SysUser();
user.setUid(UUID.randomUUID().toString());
user.setUsername("张三");
user.setUserpwd("6666");
userMapper.insert(user);
// 第二次查询,由于是同一个session则不再向数据发出语句直接从缓存取出
SysUser user2 = userMapper.findUserById(1);
System.out.println(user2);
// 关闭session
session.close();

最后结果在内存中的地址不相同,说明两次查询的结果不是同一个。

edu.mybatis2.pojo.SysUser@6b9651f3
edu.mybatis2.pojo.SysUser@262b2c86

三、二级缓存

1、原理

在这里插入图片描述
二级缓存区域是根据mapper的namespace划分的,相同的namespace的mapper查询的数据放在同一个区域,如果使用mapper代理方法每个mapper的namespace都不同,此时可以理解为二级缓存区域是根据mapper。
每次查询都会先从缓存查找,如果找不到从数据库查询,查询到数据将数据写入缓存。Mybatis 内部存储缓存使用一个 HashMap,key 为hashCode+sqlId+Sql 语句。value 为 从查询出来的结果数据 。sqlSession 执行 insert、update、delete 等操作 commit 提交后会清空缓存区域。

2、开启二级缓存

在核心配置文件中加入

<settings>
    <setting name="cacheEnabled" value="true"/>
</settings>

要在你的 Mapper 映射文件中添加一行: < cache /> ,表示此 mapper 开启二级缓存。

3、测试

//获取session
SqlSession session1 = sessionFactory.openSession();
//获限mapper接口实例
SysUserDao userMapper1 = session1.getMapper(SysUserDao.class);
//第一次查询
SysUser user1 = userMapper1.findUserById(1);
System.out.println(user1);
session1.close();
SqlSession session2 = sessionFactory.openSession();
SysUserDao userMapper2 = session2.getMapper(SysUserDao.class);
// 第二次查询,由于是同一个session则不再向数据发出语句直接从缓存取出
SysUser user2 = userMapper2.findUserById(1);
System.out.println(user2);
// 关闭session
session2.close();

ps:验证方式,debug模式下人为修改数据库可验证。

4、实现序列化

二级缓存需要查询结果映射的 pojo 对象实现 java.io.Serializable 接口实现序列化和反序 列化操作,注意如果存在父类、成员 pojo 都需要实现序列化接口。

public class SysUser implements Serializable

5、禁用二级缓存

在 statement 中设置 useCache=false 可以禁用当前 select 语句的二级缓存,即每次查询都会 发出 sql 去查询,默认情况是 true,即该 sql 使用二级缓存。

 <select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">

6、刷新缓存

在 mapper 的同一个 namespace 中,如果有其它 insert、update、delete 操作数据后需要刷新 缓存,如果不执行刷新缓存会出现脏读。
设置 statement 配置中的 flushCache=“true” 属性,默认情况下为 true 即刷新缓存,如果改成 false 则不会刷新。
使用缓存时如果手动修改数据库表中的查询数据会出现脏读。 如下:

<insert id="insertUser" parameterType="edu.etime.mybatis.pojo.User" flushCache="true">
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值