美文网首页
Mybatis缓存——一级缓存

Mybatis缓存——一级缓存

作者: 程序员点点 | 来源:发表于2021-01-20 22:30 被阅读0次

缓存的重要性是不言而喻的。 使用缓存, 我们可以避免频繁的与数据库进行交互, 尤其是在查询越多、缓存命中率越高的情况下, 使用缓存对性能的提高更明显。

mybatis 也提供了对缓存的支持, 分为一级缓存和二级缓存。 但是在默认的情况下, 只开启一级缓存(一级缓存是对同一个 SqlSession 而言的)。

以下的项目是在mybatis 初步使用(IDEA的Maven项目, 超详细)的基础上进行。

对以下的代码, 你也可以从我的GitHub中获取相应的项目。

1 一级缓存

同一个 SqlSession 对象, 在参数和 SQL 完全一样的情况先, 只执行一次 SQL 语句(如果缓存没有过期)

也就是只有在参数和 SQL 完全一样的情况下, 才会有这种情况。

1.1 同一个 SqlSession

@Test
public void oneSqlSession() {
    SqlSession sqlSession = null;
    try {
        sqlSession = sqlSessionFactory.openSession();

        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        // 执行第一次查询
        List<Student> students = studentMapper.selectAll();
        for (int i = 0; i < students.size(); i++) {
            System.out.println(students.get(i));
        }
        System.out.println("=============开始同一个 Sqlsession 的第二次查询============");
        // 同一个 sqlSession 进行第二次查询
        List<Student> stus = studentMapper.selectAll();
        Assert.assertEquals(students, stus);
        for (int i = 0; i < stus.size(); i++) {
            System.out.println("stus:" + stus.get(i));
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (sqlSession != null) {
            sqlSession.close();
        }
    }
}

在以上的代码中, 进行了两次查询, 使用相同的 SqlSession, 结果如下


image.png

在日志和输出中:

第一次查询发送了 SQL 语句, 后返回了结果;

第二次查询没有发送 SQL 语句, 直接从内存中获取了结果。

而且两次结果输入一致, 同时断言两个对象相同也通过。

1.2 不同的 SqlSession

@Test
public void differSqlSession() {
    SqlSession sqlSession = null;
    SqlSession sqlSession2 = null;
    try {
        sqlSession = sqlSessionFactory.openSession();

        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        // 执行第一次查询
        List<Student> students = studentMapper.selectAll();
        for (int i = 0; i < students.size(); i++) {
            System.out.println(students.get(i));
        }
        System.out.println("=============开始不同 Sqlsession 的第二次查询============");
        // 从新创建一个 sqlSession2 进行第二次查询
        sqlSession2 = sqlSessionFactory.openSession();
        StudentMapper studentMapper2 = sqlSession2.getMapper(StudentMapper.class);
        List<Student> stus = studentMapper2.selectAll();
        // 不相等
        Assert.assertNotEquals(students, stus);
        for (int i = 0; i < stus.size(); i++) {
            System.out.println("stus:" + stus.get(i));
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (sqlSession != null) {
            sqlSession.close();
        }
        if (sqlSession2 != null) {
            sqlSession2.close();
        }
    }
}

在代码中, 分别使用 sqlSession 和 sqlSession2 进行了相同的查询。

其结果如下


image.png

从日志中可以看到两次查询都分别从数据库中取出了数据。 虽然结果相同, 但两个是不同的对象。

1.3 刷新缓存

刷新缓存是清空这个 SqlSession 的所有缓存, 不单单是某个键。

@Test
public void sameSqlSessionNoCache() {
    SqlSession sqlSession = null;
    try {
        sqlSession = sqlSessionFactory.openSession();

        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        // 执行第一次查询
        Student student = studentMapper.selectByPrimaryKey(1);
        System.out.println("=============开始同一个 Sqlsession 的第二次查询============");
        // 同一个 sqlSession 进行第二次查询
        Student stu = studentMapper.selectByPrimaryKey(1);
        Assert.assertEquals(student, stu);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (sqlSession != null) {
            sqlSession.close();
        }
    }
}

如果是以上, 没什么不同, 结果还是第二个不发 SQL 语句。

在此, 做一些修改, 在 StudentMapper.xml 中, 添加
flushCache=“true”
修改后的配置文件如下:

<select id="selectByPrimaryKey" flushCache="true" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List" />
    from student
    where student_id=#{id, jdbcType=INTEGER}
</select>

结果如下:


image.png

第一次, 第二次都发送了 SQL 语句, 同时, 断言两个对象相同出错。

1.4 总结

  1. 在同一个 SqlSession 中, Mybatis 会把执行的方法和参数通过算法生成缓存的键值, 将键值和结果存放在一个 Map 中, 如果后续的键值一样, 则直接从 Map 中获取数据;
  2. 不同的 SqlSession 之间的缓存是相互隔离的;
  3. 用一个 SqlSession, 可以通过配置使得在查询前清空缓存;
  4. 任何的 UPDATE, INSERT, DELETE 语句都会清空缓存。

版权声明:本文为阿进的写字台原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_37139197/article/details/82908377

相关文章

  • mybatis一级缓存和二级缓存

    MyBatis官网MyBatis拥有自带一级缓存和二级缓存 一级缓存: MyBatis是默认开启一级缓存,一级缓存...

  • MyBatis缓存书目录

    MyBatis缓存 MyBatis介绍 MyBatis一级缓存 1、什么是一级缓存? 为什么使用一级缓存? 2、M...

  • 你真的懂Mybatis缓存机制吗

    MyBatis自带的缓存有一级缓存和二级缓存。 一级缓存 Mybatis的一级缓存是指Session缓存。一级缓存...

  • java基础面试题总结——其他大型框架

    1. 简述mybatis缓存机制的实现原理 mybatis缓存分为一级缓存和二级缓存: 一级缓存 概念:一级缓存即...

  • Mybatis缓存机制:一级缓存与二级缓存

    MyBatis的缓存分为一级缓存(本地缓存)和二级缓存 1、一级缓存 MyBatis的一级缓存是默认会开启的并且不...

  • MyBatis源码解析(四) Cache模块

    MyBatis的二级缓存 MyBatis的缓存分为一级缓存和二级缓存,一级缓存是 SqlSession 级别的缓存...

  • 2019-10-09 mybatis理解

    1、讲下 MyBatis 的缓存 MyBatis 的缓存分为一级缓存和二级缓存,一级缓存放在 session 里面...

  • Mybatis缓存

    mybatis分为一级缓存和二级缓存,在默认的情况下,Mybatis只会开启一级缓存 一级缓存 一级缓存是一次会话...

  • [java]38、MyBatis缓存

    1、缓存 MyBatis的缓存分为一级缓存、二级缓存,用于缓存select的结果 1.1、一级缓存 一级缓存是存放...

  • mybatis的缓存

    mybatis的缓存分为一级缓存和二级缓存。一级缓存也叫本地缓存,mybatis会默认启用,并且不会被更改。通常说...

网友评论

      本文标题:Mybatis缓存——一级缓存

      本文链接:https://www.haomeiwen.com/subject/ggplzktx.html