【Mybatis】一级缓存

本文深入探讨了MyBatis的缓存概念及其重要性,解释了适合缓存的数据类型,并详细介绍了MyBatis的一级缓存工作原理和失效条件。通过实例展示了如何测试一级缓存,包括查询不同对象、增删改操作、使用不同Mapper以及手动清理缓存等情况。总结了一级缓存失效的四种情况,强调了缓存对于提升系统性能的关键作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.什么是缓存[Cache ]?

2.为什么使用缓存?(缓存的意义,目的)

3.什么样的数据能使用缓存?

4.Mybatis缓存

5.Mybatis缓存的适用场景以及测试

一级缓存

6.一级缓存失效的四种情况:

1.一次性查询不同的对象

2.增删改会刷新缓存

3.运行不同的mapper

4.手动清理缓存

总结


1.什么是缓存[Cache ]?


缓存是存在内存中的临时数据。


将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。


2.为什么使用缓存?(缓存的意义,目的)


减少和数据库的交互次数,减少系统开销,提高系统效率。

3.什么样的数据能使用缓存?


经常查询并且不经常改变的数据。(说白了就是查的数据)

反过头来说,经常改变的数据(也就是增删改的数据)就不适合作为缓存的数据,因为它如果改变一次就缓存一次就会造成系统开销,实属没必要。

4.Mybatis缓存


MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地定制和配置缓存。缓存可以极大的提升查询效率。

 MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存


 默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称为本地缓存)。

二级缓存需要手动开启和配置,他是基于namespace级别的缓存。


为了提高扩展性,MyBatis定义了缓存接口cache。我们可以通过实现Cache接口来自定义二级缓存

5.Mybatis缓存的适用场景以及测试

一级缓存

让我们来测试一级缓存:

public interface UserMapper {
    List<User> getUserById(@Param("id")int id);
}
<mapper namespace="com.kxy.mapper.UserMapper">
    <select id="getUserById" resultType="User">
        select * from user where id = #{id}
    </select>
</mapper>
 @Test
    public void Test(){
        SqlSession sqlSession = MyUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user1 = mapper.getUserById(1);
        System.out.println(user1);
        System.out.println("============");
        User user2 = mapper.getUserById(1);
        System.out.println(user2);
        System.out.println(user1==user2);
        sqlSession.close();
    }

 可以发现sql只走了一次,这说明当我们第一次查第id为1的User时,只要他没有被改变,就会被存入一级缓存(本地缓存)中,那么如果再查一次它,就不用去执行sql了,而是从一级缓存中去取。这就是一级缓存的作用之一。

比如下面这个例子:我们修改了Test方法,先查id为1的user1,然后查id为2的user2,最后查id为1user3(user3==user1)

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

 

 至于蓝色标记的id为2的user,他并不影响user1存入缓存,为user3去取提供方便的事实。因此也验证了我们那句话:只要他没有被改变(刷新缓存除外),就会被存入一级缓存(本地缓存)中。

6.一级缓存失效的四种情况:

1.一次性查询不同的对象

比如我先查了id为1的user,我又查询了id为2的user,想都不用想,肯定不会缓存。

2.增删改会刷新缓存

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("==============");
        mapper.updateUserById(new User(2,"kxy","1434134"));
        System.out.println("==============");
        User user2 = mapper.getUserById(1);
        System.out.println(user2);
        System.out.println(user1==user2);
        sqlSession.commit();
        sqlSession.close();
    }

 

像这种情况,增删改操作导致的数据可能会改变原来的数据,即便改变的不是当前对象,也会刷新缓存,从而导致第二次读取执行sql从数据库里重新查了一次。重新开辟了地址给user2,所以use1==user2是false,即他们不是同一个对象。其本质:地址不同,值相同。

由此可见:增删改会刷新缓存,刷新缓存产生新的对象。

3.运行不同的mapper

因为一个mapper对应一个sqlsession(sqlsession.getMapper),而一级缓存的作用范围只在sqlsession(从sqlsession创建到sqlsession关闭),因此运行不同的mapper当然不会实现一级缓存。

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.clearCache();
        System.out.println("==============");
        User user2 = mapper.getUserById(1);
        System.out.println(user2);
        System.out.println(user1==user2);
        sqlSession.close();
    }

 显然sql运行了两次,第二次没有从缓存中拿,是因为缓存被清理了。false是因为从数据库中又查了一遍,从jdbc的角度来讲,他每次查询都产生一个resultset类型的对象,因此对象肯定是新的对象,其本质:地址不同,值相同。

由此可见:清空缓存会产生新的对象。

总结

1.只要他没有被改变(刷新缓存除外),就会被存入一级缓存(本地缓存)中。

2.增删改会刷新缓存,刷新缓存产生新的对象。

3.清空缓存会产生新的对象。


一级缓存失效的四种情况:

1.一次性查询不同的对象。

2.增删改会刷新缓存

3.运行不同的mapper

4.手动清理缓存

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

❀༊烟花易冷ღ

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

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

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

打赏作者

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

抵扣说明:

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

余额充值