Mybatis缓存小谈

本文介绍了Mybatis的一级和二级缓存。一级缓存是SqlSession级别的,默认开启,但在增删改操作后会清空。二级缓存是Mapper级别的,缓存数据而非对象,需手动配置开启。在增删改同一Mapper的操作后,二级缓存会被清空。
摘要由CSDN通过智能技术生成

Mybatis缓存

1.Mybatis缓存介绍

众所周知频繁的对数据库进行查询操作,存在严重的性能问题,而Mybatis作为一个持久层的框架,为了解决这种问题,像其他框架一样,提供了缓存的技术,这里稍微提一下,MyBatis的持久层操作是通过代理对象实现的。

Mybatis提供了两种缓存:

  • 一级缓存

一级缓存为一级缓存是SqlSession级别的缓存,只要当前SqlSession没有commit或close,它就存在,当然当前SqlSession对数据库执行增删改操作时,一级缓存也会相应清空。一级缓存与生俱来,默认即开启并使用。

这里使用代码证明:

    public void testFindAll(){

        User user1 = new User();
        user1.setId(41);
        user1.setUsername("张三");

        User user2 = new User();
        user1.setId(42);
        user1.setUsername("张三");

        //sqlSession对象1
        SqlSession sqlSession = factory.openSession();
        //sqlSession对象2
        SqlSession sqlSession2 = factory.openSession();
        //获取代理对象1
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //获取代理对象2
        UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
        //代理对象1查询
        List<User> users1 = mapper.findAll();
        List<User> users2 = mapper.findAll();
        //提交
        sqlSession.commit();
        //提交后再次查询
        List<User> users3=mapper.findAll();
        //sqlSession对象2更新
        mapper2.update(user1);
        sqlSession2.commit();
        List<User> users4=mapper.findAll();
        //sqlsession对象1更新
        mapper.update(user2);
        List<User> users5=mapper.findAll();
        System.out.println("未commit:"+(users1==users2));
        System.out.println("commit:"+(users1==users3));
        System.out.println("sqlsession2执行更新:"+(users3==users4));
        System.out.println("sqlsession1执行更新:"+(users3==users5));
    }

输出结果:

未commit:true
commit:false
sqlsession2执行更新:true
sqlsession1执行更新:false

以上代码结果证明:

1.一级缓存在执行commit()会被清除,其实close(),clearCache()方法,同样会清空一级缓存。

2.一级缓存在sqlSession执行修改操作时,会清空一级缓存-----注意:这里的mapper代理对象执行命令底层实际还是调用了sqlSession。

3.另一个sqlSession对象对数据库执行增删改方法时,并不会清除此sqlSession对象的一级缓存。所以这个安全问题需要注意,虽然正常并不会有人这样写代码。

4.上面的比较使用的是“==”,所以比较的是地址,即一级缓存缓存的是对象,所以才可能实现地址相同。

 


  • 二级缓存

二级缓存为Mapper级别的缓存,即只要是属于同一个Mapper的查询操作就可以共享缓存。

关系如下图所示:

二级缓存有几个特点:

1.缓存的是数据,而不是对象(这一点与一级缓存不同),需要注意。

2.二级缓存在sqlsession执行commit()方法后才会被写入。

3.不同的sqlsession执行增删改方法,只要操作的是同一个mapper就会清空二级缓存区域。

4.查询数据时,优先从二级缓存区获取数据,如果二级缓存区没有数据,才会找一级缓存区。

下面使用代码证明:

注意:我这里开启了二级缓存。

    public void testFindAll(){
        User user1 = new User();
        user1.setId(41);
        user1.setUsername("张wu");

        //sqlSession对象1
        SqlSession sqlSession = factory.openSession();
        //sqlSession对象2
        SqlSession sqlSession2 = factory.openSession();
        //获取代理对象1
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //获取代理对象2
        UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
        //代理对象1查询
        List<User> users1 = mapper.findAll();
        List<User> users2 = mapper.findAll();
        //提交
        sqlSession.commit();
        //提交后再次查询(两次)
        List<User> users3=mapper.findAll();
        List<User> users4=mapper.findAll();
        //sqlSession对象2更新
        mapper2.update(user1);
        sqlSession2.commit();
        List<User> users5=mapper.findAll();

        System.out.println("未执行commit:"+(users1==users2));
        System.out.println("执行commit:"+(users1==users3));
        System.out.println("二级缓存与一级缓存共存时:"+(users3==users4));
        System.out.println("sqlsession2执行更新操作:"+(users4==users5));
    }

运行结果如下:

未执行commit:true
执行commit:false
二级缓存与一级缓存共存时:false
sqlsession2执行更新操作:false

与上述的log一并分析:

1.输出结果一为位执行commit()时,使用一级缓存查询的结果,对象地址相同。

2.输出结果为,执行commit()前后,使用使用二级缓存获得的数据(对应log中的0.33333),封装为新对象。

3.输出结果为:二级缓存和一级缓存(查询users3时存在的一级缓存)并存时,从二级缓存拿数据(对应log中的0.5)

4.输出结果为:sqlsession2执行更新操作后,重新进行查询封装。参照log红框中标注的sql语句(重新从数据库查询)。

 

2.如何开启二级缓存

1.配置文件方式:

主配置文件中添加如下标签:
<settings>
    <setting name="cachedEnabled" value="true">    <!--(默认为true,可以不设置)-->
</settings>

Mapper映射文件添加如下标签:
<cache />     <!--不能省略-->
<select id="" resultType="" useCache="true">       <!-- sql映射select语句中的useCache属性 (默认为true,可以不设置)-->

</select>       

2.注解方式:

@CacheNamespace(blocking = true)

将此注解加在Mapper类上,即表明此Mapper类启用二级缓存

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值