【Mybatis】二级缓存

目录

二级缓存

如何开启二级缓存?

1.设置全局缓存为true(可省略,因为二级缓存默认开启)

 2.在 SQL 映射文件(mapper)中添加cache标签

3.会话关闭或提交后实现二级缓存

4.增删改会刷新缓存

5.一级缓存、二级缓存、与数据库的联系

缓存机制流程总结:


二级缓存

二级缓存也叫全局缓存,一级缓存作用域(sqlsession级别)太低了,所以诞生了二级缓存基于namespace级别(mapper)的缓存,一个名称空间,对应一个二级缓存

工作机制:
。一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;
。如果当前会话(sqlsession)关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中;
。新的会话查询信息,就可以从二级缓存中获取内容;
。不同的mapper查出的数据会放在自己对应的缓存(map)中;
 

如何开启二级缓存?

1.设置全局缓存为true(可省略,因为二级缓存默认开启)

    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>

 2.在 SQL 映射文件(mapper)中添加cache标签

<mapper namespace="com.kxy.mapper.UserMapper">
    <cache/>
    <select id="getUserById" resultType="User" useCache="true">
        select * from user where id = #{id}
    </select>
    <update id="updateUserById" parameterType="User">
        update user set pwd = #{pwd},name =#{name} where id = #{id};
    </update>
</mapper>

 默认的效果如下:

  • 映射语句文件中的所有 select 语句的结果将会被缓存。
  • 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
  • 缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。
  • 缓存不会定时进行刷新(也就是说,没有刷新间隔)。
  • 缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。
  • 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

如果使用默认的cache标签,则(只读属性)readOnly默认值为false。也就是可读写,而可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全。如果是false,则需要让实体类实现序列化接口,否则不能正常读写。出现报错。

3.会话关闭或提交后实现二级缓存

在测试类中,我们每创建一个sqlsession,并实现了它的读操作,关闭后立马创建sqlsession1,保证了在一个时间段里只存在一个sqlsession,也就是说sqlsession关闭后,才将数据存入二级缓存中,从而sqlsession1创建后,从全局缓存(二级缓存)取出数据。

@Test
    public void Test1(){
        SqlSession sqlSession = MyUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user1 = mapper.getUserById(1);
        System.out.println(user1);
        sqlSession.close();
        System.out.println("==============");
        SqlSession sqlSession1 = MyUtils.getSqlSession();
        UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
        User user2 = mapper1.getUserById(1);
        System.out.println(user2);
        sqlSession1.close();
        System.out.println(user1==user2);
    }

可以看到sql只运行了一次,并且第二个会话运行时,是从本地缓存里取得数据,没有执行sql。 false则是因为sqlsession是不同的,因此产生的对象(哈希值)地址值不同。

但是如果像这样:在第一个会话还没关闭之前就运行第二个会话,那么两个会话(线程)都没有关闭,是不会缓存的

 @Test
    public void Test1(){
        SqlSession sqlSession = MyUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user1 = mapper.getUserById(1);
        System.out.println(user1);
        System.out.println("==============");
        SqlSession sqlSession1 = MyUtils.getSqlSession();
        UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
        User user2 = mapper1.getUserById(1);
        System.out.println(user2);
        sqlSession.close();
        sqlSession1.close();
        System.out.println(user1==user2);
    }

 

 所以只需要保证会话关闭后,第二个会话才能从全局缓存中取出数据。 

4.增删改会刷新缓存

@Test
    public void Test1(){
        SqlSession sqlSession = MyUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user1 = mapper.getUserById(1);
        System.out.println(user1);
        sqlSession.close();
        System.out.println("==============");
        SqlSession sqlSession1 = MyUtils.getSqlSession();
        UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
        mapper1.updateUserById(new User(2,"xx","14213"));
        sqlSession1.commit();
        System.out.println("==============");
        SqlSession sqlSession2 = MyUtils.getSqlSession();
        UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
        User user2 = mapper2.getUserById(1);
        System.out.println(user2);
        sqlSession2.close();
    }

 

因此增删改无论是对于一级缓存还是二级缓存,都会刷新缓存!

5.一级缓存、二级缓存、与数据库的联系

 

 优先级:二级缓存>一级缓存>数据库

缓存机制流程总结:

先看二级缓存有没有(会话关闭或提交后产生),如果有就拿。如果没有则看一级缓存(在同一个会话里查询后产生)有没有,如果有就拿,没有就去数据库里拿(jdbc预处理对象执行sql)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

❀༊烟花易冷ღ

觉得博客写的不错就打赏一下吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值