远方的灯塔 - 专注于服务端技术分享 远方的灯塔 - 专注于服务端技术分享
首页
  • Java SE
  • Struts2
  • Hibernate
  • MyBatis
  • JAX-WS
  • 并发
  • 分布式
  • Git
  • 文章分类
  • 文章标签
  • 文章归档
  • 《C程序设计语言》
心情随笔
友情链接
给我留言 (opens new window)
关于我
GitHub (opens new window)

Terwer Green

一个后端老菜鸟
首页
  • Java SE
  • Struts2
  • Hibernate
  • MyBatis
  • JAX-WS
  • 并发
  • 分布式
  • Git
  • 文章分类
  • 文章标签
  • 文章归档
  • 《C程序设计语言》
心情随笔
友情链接
给我留言 (opens new window)
关于我
GitHub (opens new window)
  • JavaSE

  • 开源框架

    • MyBatis

      • JDBC的问题分析
      • 自定义持久层框架的设计思路
      • 自定义持久层框架的代码实现一
      • 自定义持久层框架的代码实现二
      • 使用getMapper方式对自定义持久层框架进行优化
      • MyBatis的基本介绍及优势
      • MyBatis的基本使用
      • Mybatis基本流程及配置文件解析
      • MyBatis复杂映射开发之一对一查询
      • MyBatis复杂映射开发之一对多查询
      • MyBatis复杂映射开发之多对多查询
      • MyBatis常用注解及基本增删改查的注解实现
      • MyBatis的注解实现复杂映射开发
      • MyBatis缓存的概念
      • MyBatis的一级缓存
      • MyBatis的二级缓存
        • 二级缓存的原理
        • 如何使用二级缓存
          • 开启二级缓存
          • useCache 和 flushCache
      • MyBatis的二级缓存整合redis
      • MyBatis-RedisCache源码分析
  • Linux

  • Struts2

  • Hibernate

  • Webservice

  • 分布式

  • 分布式框架

  • 后端开发
  • 开源框架
  • MyBatis
terwer
2022-09-24
目录

MyBatis的二级缓存

# 二级缓存的原理

二级缓存的原理和一级缓存一样,第一次查询会将数据放到缓存中,然后第二次查询直接去缓存读取。

但是一级缓存是基于 SqlSession 的,二级缓存是基于 mapper 的 namespace 的。

也就是说,多个 SqlSession 可以共享同一个二级缓存区域。如果两个 mapper 的 namespace 相同,那么即使是两个 mapper,这两个 mapper 执行 sql 查询的数据也将保存在相同的二级缓存区域中。

​

# 如何使用二级缓存

注意:User 需要实现序列化接口。

# 开启二级缓存

和一级缓存不一样,二级缓存需要手动开启。

首先在全局配置文件 sqlMapConfig.xml 中加入如下代码

<settings>
    <!-- 开启二级缓存 -->
    <setting name="cacheEnabled" value="true"/>
</settings>
1
2
3
4

然后在 UserMapper.xml 中开启二级缓存。

<!-- 开启二级缓存 -->
<cache />
1
2

如果是使用注解方式,在 IUserMapper 上写上注解 @CacheNamespace

@CacheNamespace
public interface IUserMapper {
}
1
2
3

测试代码

public class SecondCacheTest {
    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void before() throws Exception {
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
    }

    @Test
    public void secondLevelCache() {
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();

        IUserMapper userMapper1 = sqlSession1.getMapper(IUserMapper.class);
        IUserMapper userMapper2 = sqlSession2.getMapper(IUserMapper.class);

        User user1 = userMapper1.findUserById(1);
        // 清空一级缓存
        sqlSession1.close();
        User user2 = userMapper2.findUserById(1);
        System.out.println(user1 == user2);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

效果如下

Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@56528192]
==>  Preparing: select * from user where id=?
==> Parameters: 1(Integer)
<==    Columns: id, username, password, birthday
<==        Row: 1, lucy, 123, 2019-12-12
<==      Total: 1
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@56528192]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@56528192]
Returned connection 1448247698 to pool.
As you are using functionality that deserializes object streams, it is recommended to define the JEP-290 serial filter. Please refer to https://docs.oracle.com/pls/topic/lookup?ctx=javase15&id=GUID-8296D8E8-2B93-4B9A-856E-0A65AF9B8C66
Cache Hit Ratio [com.terwergreen.mapper.IUserMapper]: 0.5
false
1
2
3
4
5
6
7
8
9
10
11
12

可以看到,两次请求,只有第一次输出了 sql , 并且输出了缓存命中率是 0.5 。

# useCache 和 flushCache

  • useCache 用来设置是否禁用二级缓存。在 statement 中设置 useCache="false" 可以禁用当前 select 语句的二级缓存

  • <select id="selectUserByUserId" useCache="false" resultType="space.terwer.pojo.User"
    parameterType="int">
      select * from user where id=#{id}
    </select>
    
    1
    2
    3
    4
  • 设置 statement 的 flushCache="true" 即 刷新缓存 ,默认情况下就是 true。因为一般不设置,默认即可。

  • 注解方式使用

    /**
     * 根据ID查询用户
     *
     * @param id
     * @return
     */
    @Options(useCache = false, flushCache = Options.FlushCachePolicy.TRUE)
    @Select("select * from user where id=#{id}")
    User findUserById(Integer id);
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

文章更新历史

2022-12-25 feat: 初稿

编辑 (opens new window)
#二级缓存#mybatis
上次更新: 2023/02/22, 13:47:25
MyBatis的一级缓存
MyBatis的二级缓存整合redis

← MyBatis的一级缓存 MyBatis的二级缓存整合redis→

最近更新
01
解决css部分border被圆角切掉之后圆角的边框消失问题
03-18
02
使用TypeScript开发一个自定义的Node-js前端开发脚手架
03-08
03
Github-Actions使用release-please实现自动发版
03-06
更多文章>
Theme by Vdoing | Copyright © 2011-2023 Terwer Green | MIT License | 粤ICP备2022020721号-1 | 百度统计
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式