08 Mybatis 缓存

作者: better_future | 来源:发表于2020-04-25 13:19 被阅读0次

Mybatis 作为持久层框架也提供了缓存策略,提供缓存策略来减少数据库的查询,提高性能。


image.png

一、Mybati 一级缓存

一级缓存是 SqlSession 级别的缓存,只要 SqlSession 没有 flush 或 close,它就存在。默认是开启的
测试根据id查询用户

@Test
    public void findById(){
        User user1 = userMapper.findById(41);
        System.out.println("第一次查:"+user1);
        User user2 = userMapper.findById(41);
        System.out.println("第二次查:"+user1);
        System.out.println(user1 == user2);
    }

结果

第一次查:User(id=41, username=老王, birthday=Tue Feb 27 17:47:08 CST 2018, sex=男, address=北京, accounts=null)
第二次查:User(id=41, username=老王, birthday=Tue Feb 27 17:47:08 CST 2018, sex=男, address=北京, accounts=null)
true

sql记录


image.png

因此,两个查询的对象完全相同,而且第二次的查询没有发出sql语句。
那么一级缓存会存在读取到可能已经修改的数据怎么办?(脏读)

一级缓存的分析

一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改添加删除commit()close()等方法时,就会清空一级缓存。

image.png

第一次发起查询用户 id 为 1 的用户信息,先去找缓存中是否有 id 为 1 的用户信息,如果没有,从数据库查询用户信息。得到用户信息,将用户信息存储到一级缓存中。

如果 sqlSession 去执行 commit 操作(执行插入、更新、删除),清空 SqlSession 中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。

第二次发起查询用户 id 为 1 的用户信息,先去找缓存中是否有 id 为 1 的用户信息,缓存中有,直接从缓存中获取用户信息。

测试清空一级缓存 使用commit
 @Test
    public void findById(){
        User user1 = userMapper.findById(41);
        System.out.println("第一次查:"+user1);
        session.commit();
        User user2 = userMapper.findById(41);
        System.out.println("第二次查:"+user1);
        System.out.println(user1 == user2);
    }

结果


image.png

发出了两次的查询,而且两次查询的返回对象都是不同的。即清空了一级缓存,而且发出了两次的sql查询。

一、Mybati 二级缓存

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

image.png
第1步:开启二级缓存

在 SqlMapConfig.xml 文件开启二级缓存

<settings>
<!-- 开启二级缓存的支持 -->
    <setting name="cacheEnabled" value="true"/>
</settings>
第2步:配置相关的 Mapper 映射文件
<mapper namespace="com.it.Mapper.UserMapper">
    <!-- 开启二级缓存的支持 -->
    <cache></cache>
</mapper>

<cache>标签表示当前这个 mapper 映射将使用二级缓存,区分的标准就看 mapper 的 namespace 值。

第3步:置 配置 statement 上面的 useCache
<!-- 根据 id 查询 -->
<select id="findById" resultType="user" parameterType="int" useCache="true">
select * from user where id = #{uid}
</select>

将 UserDao.xml 映射文件中的<select>标签中设置 useCache="true"代表当前这个 statement 要使用二级缓存,如果不使用二级缓存可以设置为 false。

注意:针对每次查询都需要最新的数据 sql,要设置成 useCache=false,禁用二级缓存。避免脏读。

二级缓存测试:
那么二级缓存的测试就需要用不同的SqlSession来操作了。

@Before//在测试方法执行之前执行
    public void init()throws Exception {
        //1.读取配置文件
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建构建者对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //3.创建 SqlSession 工厂对象
        factory = builder.build(in);
        //4.创建 SqlSession 对象
        session1 = factory.openSession();
        session2 = factory.openSession();
        //5.创建 Dao 的代理对象
        userMapper1 = session1.getMapper(UserMapper.class);
        userMapper2 = session2.getMapper(UserMapper.class);
    }

测试一

@Test
    public void findById(){
        User user1 = userMapper1.findById(41);
        System.out.println("第一次查:"+user1);
        User user2 = userMapper2.findById(41);
        System.out.println("第二次查:"+user2);
        System.out.println(user1 == user2);
    }

这里session1的mapper查询完,立马使用session2去查询


image.png

可以看到发出了两次的sql查询。

测试二
先用一个session去查,查完了关闭session1(即关闭了session1一级缓存),然后再用session2去查询

@Test
    public void findById(){
        User user1 = userMapper1.findById(41);
        System.out.println("第一次查:"+user1);

        session1.close(); //将一级缓存关闭

        User user2 = userMapper2.findById(41);
        System.out.println("第二次查:"+user2);
        System.out.println(user1 == user2);
    }
image.png

只发出了一次sql查询语句,用的是session1的二级缓存
但是查询到的对象是不同的,也就是说,session2用session1中的二级缓存结果重新开辟的一个新的对象,内容相同。

二级缓存注意事项
  • 当我们在使用二级缓存时,所缓存的类一定要实现 java.io.Serializable 接口,这种就可以使用序列化方式来保存对象。

相关文章

  • mybatis 08 缓存

    概念:mybatis缓存也称为查询缓存 一级缓存:一级缓存是SqlSession级别的缓存;当一个sqlsessi...

  • 08 Mybatis 缓存

    Mybatis 作为持久层框架也提供了缓存策略,提供缓存策略来减少数据库的查询,提高性能。 一、Mybati 一级...

  • MyBatis缓存和注解

    Mybatis缓存和注解 学习目标 1、mybatis缓存 2、mybatis注解 学习内容 1、mybatis缓...

  • MyBatis缓存书目录

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

  • MyBatis缓存配置

    这篇我们讲MyBatis的缓存配置,关于MyBatis缓存请参看MyBatis缓存。在xml配置爱中添加如下内容:...

  • Mybatis的缓存

    一 Mybatis缓存体系图 Mybatis缓存的基础实现是perpetualCache,但是mybatis利用装...

  • 【MyBatis】学习纪要八:缓存(二)

    缓存工具 MyBatis缓存 Ehcache Redis 缓存设计 缓存接口 我们来讨论一下,说到MyBatis,...

  • mybatis一级缓存和二级缓存

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

  • Mybatis缓存机制详解2019-06-13

    mybatis缓存机制详解 mybatis提供了缓存机制减轻数据库压力,提高数据库性能 mybatis的缓存分为两...

  • Mybatis 源码分析(三)之 Mybatis 的一级缓存和二

    Mybatis 源码分析(三)之 Mybatis 的一级缓存和二级缓存 Mybatis系列:Mybatis 基础介...

网友评论

    本文标题:08 Mybatis 缓存

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