Mybatis缓存机制

系列文章目录
Mybatis学习笔记Ⅰ
Mybatis学习笔记Ⅱ



一、Mybatis缓存

    Mybatis 一级缓存的作用域是同一个 SqlSession,在同一个 sqlSession 中两次执行相同的 sql 语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。当一个 sqlSession 结束后该 sqlSession 中的 一级缓存也就不存在了。Mybatis 默认开启一级缓存。

    Mybatis 二级缓存是多个 SqlSession 共享的,其作用域是 mapper 的同一个 namespace,不同 的 sqlSession 两次执行相同 namespace 下的 sql 语句且向 sql 中传递参数也相同即最终执行 相同的 sql 语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从 缓存中获取数据将不再从数据库查询,从而提高查询效率。Mybatis 默认没有开启二级缓存 需要在 setting 全局参数中配置开启二级缓存。

在这里插入图片描述

二、一级缓存

在这里插入图片描述

测试一级缓存

测试1:

    public void testFindDepartmentById1(){
        SqlSession session = MybatisUtils.openSession();
        DepartmentMapper departmentMapper = session.getMapper(DepartmentMapper.class);
        //第一次查询
        Department department1 = departmentMapper.findDepartmentById(1);
        System.out.println(department1);
        //第二次查询,由于是同一个session则不再向数据发出语句直接从缓存取出
        Department department2 = departmentMapper.findDepartmentById(1);
        System.out.println(department2);
        session.close();
    }

控制台日志打印(仅执行了一次sql语句):
在这里插入图片描述

测试2:

    public void testFindDepartmentById2(){
        SqlSession session = MybatisUtils.openSession();
        DepartmentMapper departmentMapper = session.getMapper(DepartmentMapper.class);
        //第一次查询
        Department department1 = departmentMapper.findDepartmentById(20);
        System.out.println(department1);
        //在同一个session执行更新
        Department departmentUpdate = new Department();
        departmentUpdate.setDeptid(20);
        departmentUpdate.setDeptname("Louis");
        departmentUpdate.setDeptdesc("louis测试");
        departmentUpdate.setDeptstate(0);
        departmentMapper.updateDepartment(departmentUpdate);
        session.commit();
        //第二次查询,虽然是同一个session但是由于执行了更新操作session的缓存被 清空,这里重新发出sql操作
        Department department2 = departmentMapper.findDepartmentById(20);
        System.out.println(department2);
    }

控制台日志打印(因更新操作执行了两次sql语句):
在这里插入图片描述

三、二级缓存

    二级缓存区域是根据 mapper 的 namespace 划分的,相同 namespace 的 mapper 查询数据放 在同一个区域,如果使用 mapper 代理方法每个 mapper 的 namespace 都不同,此时可以理 解为二级缓存区域是根据 mapper 划分。 每次查询会先从缓存区域找,如果找不到从数据库查询,查询到数据将数据写入缓存。
在这里插入图片描述

1.配置开启二级缓存

①mybatis-config.xml加入设置

    <settings>
        <!--cacheEnabled:开启mybatis的二级缓存-->
        <setting name="cacheEnabled" value="true"/>
    </settings>

②Mapper映射文件中加入设置

    <cache/>

③实现序列化

public class Department implements Serializable {}

2.测试二级缓存

    public void testFindDepartmentById4(){
        SqlSession session1 = MybatisUtils.openSession();
        //使用session1执行第一次查询
        DepartmentMapper departmentMapper1 = session1.getMapper(DepartmentMapper.class);
        Department department1 = departmentMapper1.findDepartmentById(20);
        System.out.println(department1);
        session1.close();
        SqlSession session2 = MybatisUtils.openSession();
        //使用session2执行第二次查询,由于开启了二级缓存这里从缓存中获取数据不 再向数据库发出sql
        DepartmentMapper departmentMapper2 = session2.getMapper(DepartmentMapper.class);
        Department department2 = departmentMapper2.findDepartmentById(20);
        System.out.println(department2);
        System.out.println(department1==department2);
        session2.close();
    }

控制台日志打印(仅执行了一次sql语句):
在这里插入图片描述

四、缓存的类型

在进行缓存验证时,也想使用(department1 = department2 )的布尔值进行判断
一级缓存:使用缓存为true 不使用缓存为false
二级缓存:是否使用缓存都为false

二级缓存并不是缓存的对象?

Mapper中可对cache进行配置readOnly属性
readOnly 为只读属性, 默认为 false
false: 可读写, 在创建对象时, 会通过反序列化得到缓存对象的拷贝。 因此在速度上会相对慢一点, 但重在安全。
true: 只读, 只读的缓存会给所有调用者返回缓存对象的相同实例。 因此性能很好, 但如果修改了对象, 有可能会导致程序出问题。

我使用的默认属性,缓存的是数据而不是对象,两次都是缓存对象的拷贝,所以比较结果为false。
参考文章:
https://blog.csdn.net/m0_53077601/article/details/122220305
https://blog.csdn.net/soulweee/article/details/120931839


总结

学习了Mybatis的缓存及机制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值