前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >10. MyBatis缓存

10. MyBatis缓存

作者头像
Devops海洋的渔夫
发布2022-01-17 14:43:07
2770
发布2022-01-17 14:43:07
举报
文章被收录于专栏:Devops专栏

10. MyBatis缓存

前言

上一篇章我们已经了解了 MyBatis 加载策略,本篇章再来认识一下 MyBatis 缓存。

什么是缓存?

代码语言:javascript
复制
# 缓存和缓冲的区别
1. 缓冲: buffer
 内存中的一块区域,提高单次IO读写效率 (一次读写1024byte,要比一次读写1byte快)
  (用空间换时间)

2. 缓存:  cache 
 内存或硬盘中的一块区域, 提高多次读效率(频繁操作)
  (用空间换时间)
  (
   酷狗听歌:
   1. 第一次听歌, 这首歌在本地缓存中没有, 要从网络上下载,会下载到硬盘上,作为缓存(比较慢)
   2. 再次听歌, 这首歌本地缓存有了, 不需要网络上下载(比较快)
  )

为什么使用缓存?

“提高再次查询效率的 ”

什么样的数据适合做缓存?

“经常访问但又不经常修改的数据... ”

缓存是用来提高再次查询效率的,所有的持久层框架基本上都有缓存机制 Mybatis也提供了缓存策略,分为一级缓存,二级缓存

一级缓存

介绍

MyBatis 一级缓存是:SqlSession级别的缓存,默认开启,不需要手动配置。

下面我们来写一个案例来验证一下效果。

验证

需求:根据id查询用户

1.使用同一个 SqlSession 对象,执行两次查询,查看是否会执行两次 SQL
代码语言:javascript
复制
@Test
public void test04(){
    //1. 同一个sqlsession (同一用户)
    SqlSession session = MyBatisUtil.getSqlSession();

    //2. 第一次查询 : 要查询数据库,往缓存中放一份
    OrdersMapper mapper = session.getMapper(OrdersMapper.class);
    // 查询用户id=41的用户以及拥有的订单
    User user = mapper.findUserByIdWithOrders(41);
    System.out.println(user);

    //3. 第二次查询: 不需要, 因为一级缓存已经有了
    OrdersMapper mapper2 = session.getMapper(OrdersMapper.class);
    // 查询用户id=41的用户以及拥有的订单
    User user2 = mapper.findUserByIdWithOrders(41);
    System.out.println(user);

    MyBatisUtil.commitAndClose(session);
}
2.一级缓存需要如何才可以失效呢?
代码语言:javascript
复制
缓存失效:
1. 手动清除缓存 clearCache()
2. 执行SqlSession的C(增加)U(更新)D(删除)操作,会自动清除缓存
3. 事务结束: commit()、rollback(), close()方法, 自动清除缓存

下面我们使用 手动清除缓存 clearCache() 来演示一下缓存失效的情况,如下:

3.完整示例代码
代码语言:javascript
复制
/**
 *   一级缓存: 默认开启
 *
 *   缓存失效:
 *       1. 手动清除缓存 clearCache()
 *       2. 执行SqlSession的C(增加)U(更新)D(删除)操作,会自动清除缓存
 *       3. 事务结束: commit()、rollback(), close()方法, 自动清除缓存
 */
@Test
public void test04(){
    //1. 同一个sqlsession (同一用户)
    SqlSession session = MyBatisUtil.getSqlSession();

    //2. 第一次查询 : 要查询数据库,往缓存中放一份
    OrdersMapper mapper = session.getMapper(OrdersMapper.class);
    // 查询用户id=41的用户以及拥有的订单
    User user = mapper.findUserByIdWithOrders(41);
    System.out.println(user);

    session.clearCache(); // 手动清除缓存

    //3. 第二次查询: 不需要, 因为一级缓存已经有了
    OrdersMapper mapper2 = session.getMapper(OrdersMapper.class);
    // 查询用户id=41的用户以及拥有的订单
    User user2 = mapper.findUserByIdWithOrders(41);
    System.out.println(user);

    MyBatisUtil.commitAndClose(session);
}

分析

一级缓存是SqlSession范围的缓存,不同的SqlSession之间的缓存区域是互相不影响的,执行SqlSession的C(增加)U(更新)D(删除)操作,或者调用clearCache()、commit()、close()方法,都会清空缓存。

二级缓存

介绍

MyBatis的二级缓存虽然是默认开启的,但需要在映射文件中配置<cache/>标签才能使用,而且要求实体类的必须实现序列化接口

根据上图,前面一级缓存是指默认一次会话中的查询缓存,而二级缓存则是针对一个映射查询的多次会话的查询缓存。

下面我们来配置一下,配置一个订单表查询的二级缓存。

验证

1. mybatis全局配置,默认值就是开启了二级缓存
代码语言:javascript
复制
<settings>
   <!--
    因为cacheEnabled的取值默认就为true,所以这一步可以省略不配置。
    为true代表开启二级缓存;为false代表不开启二级缓存。
   -->
   <setting name="cacheEnabled" value="true"/>
</settings>

sqlMapConfig.xml 设置如下:

2. 指定需要开启二级缓存的映射配置文件

设置订单映射配置文件 OrdersMapper.xml 的二级缓存,如下:

代码语言:javascript
复制
<?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">
<!--
实体类的映射文件
namespace 指定接口的类全名
-->
<mapper namespace="com.lijw.dao.OrdersMapper">

    <!-- 设置二级缓存   -->
    <cache></cache>
    
</mapper>    
3.实体类要实现序列化接口
4.编写测试方法:使用两个查询sqlsession进行查询,确认二级缓存的效果
代码语言:javascript
复制
    /**
     * 二级缓存:
     * 1. 作用范围: 比一级大, 跨sqlsession
     * 2. 存储介质: 内存/硬盘
     * <p>
     * 注意:
     * 1. 核心配置文件: 默认开启,可以不设置
     * 2. 映射文件: <cache/>
     * 3. 实体类: 实现serializable接口
     * <p>
     * 开发中经常不用二级缓存
     * 1. 二级缓存数据主要在硬盘上 /  数据库的数据也在硬盘上
     * 已经查好的数据                 还得查
     * <p>
     * 效率提升不明显
     * 2. 以后用其他的技术代替mybatis 二级缓存(redis非关系型数据库)
     */
    @Test
    public void test05() {

        //1. 模拟第一个用户查询
        SqlSession session = MyBatisUtil.getSqlSession();
        OrdersMapper mapper = session.getMapper(OrdersMapper.class);
        // 查询用户id=41的用户以及拥有的订单
        User user = mapper.findUserByIdWithOrders(41);
        System.out.println(user);
        // 关闭第一个用户的查询 session
        MyBatisUtil.commitAndClose(session);

        //3. 模拟第二个用户查询(不同的SqlSession)
        SqlSession session2 = MyBatisUtil.getSqlSession();
        OrdersMapper mapper2 = session2.getMapper(OrdersMapper.class);
        // 查询用户id=41的用户以及拥有的订单
        User user2 = mapper2.findUserByIdWithOrders(41);
        System.out.println(user2);
        // 关闭第二个用户的查询 session
        MyBatisUtil.commitAndClose(session2);


    }

执行查看是否执行了两次SQL,如下:

分析

二级缓存是mapper映射级别的缓存,多个SqlSession去操作同一个Mapper映射的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。

二级缓存相比一级缓存的范围更大.

知识小结

代码语言:javascript
复制
1. mybatis的缓存,都不需要我们手动存储和获取数据。mybatis自动维护的。

2. 使用mybatis,如果是中小型项目,使用自带缓存的机制是可以满足需求的。如果是大型(分布式)项目,mybatis的缓存灵活性不足,需要使用第三方的缓存技术解决问题。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-04-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 海洋的渔夫 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 10. MyBatis缓存
    • 前言
      • 什么是缓存?
        • 为什么使用缓存?
          • 什么样的数据适合做缓存?
            • 一级缓存
              • 介绍
              • 验证
              • 分析
            • 二级缓存
              • 介绍
              • 验证
              • 分析
            • 知识小结
            相关产品与服务
            文件存储
            文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档