美文网首页
mybatis的缓存

mybatis的缓存

作者: 瓢鳍小虾虎 | 来源:发表于2020-12-04 17:24 被阅读0次

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

    一级缓存

    mybatis的一级缓存在于一次sqlSession生命周期中,mybatis的一级缓存本质是一个map,
    在同一个sqlSession查询中,mybatis会将执行的方法和参数通过一定算法生成一个key,将key和查询结果存放在map中,第二次查询如果能匹配上则直接返回上一次查询的实例。

    这里的问题是,在一次sqlSession中,第一次查询到结果后,对返回的实例对象做了set更新属性值,但是没有更新到数据库中,紧接着第二次相同条件的查询,会直接返回前一个实例,出现了非预期的情况。

    在一次sqlSession的两次查询过程中如果有任意更新操作(不限于当前数据的增删改操作),则第二次查询的返回结果会是一个新的实例,因为一级缓存被清空了。

    如果不想使用一级缓存,可以再mapper上配置flushCache="true"强制更新cache,即查询前也会强制清空当前的一级缓存。
    <select id=”selectByid” flushCache=”true”

    二级缓存

    二级缓存不同于一级缓存只存在于sqlSession生命周期中,二级缓存可以理解为存在于sqlSessionFactory周期中,与map的命名空间绑定。

    关于配置

    在mybatis的全局配置中有一个参数cacheEnabled,默认为true,如果配置成false,则二级缓存全局范围不可用,如果需要可以在mybatis-config.xml中配置:
    <settings>
    < !-- 其他配置 -->
    <setting name="cacheEnabled" value="true" />
    </settings>

    二级缓存是和命名空间绑定的,需要配置在mapper.xml文件的根节点上或者mapper.java接口上,属性名为namespace,在mapper接口上配置,命名空间就是接口的全限定名称。

    <mapper namespace=” t k . mybatis . smple.mapper . RoleMapper ”>
    <cache/>
    </mapper>

    一个cache标签即代表开启了二级缓存,二级缓存默认配置:
    1.该命名空间下的所有select会被缓存
    2.增删改操作会刷新缓存
    3.使用LRU(Least Recently Used 最近最少使用)算法回收缓存
    4.不会自动根据时间段刷新
    5.存储集合或者对象的1024个引用,即size=1024
    6.缓存是可读写的,支持多线程同时操作而不互相影响,即如果只支持读,就是返回给多个线程同样的实例,如果支持写,就是返回缓存对象的copy,各自操作各自的。

    mybatis的一级缓存和二级缓存本质都是内存级别的缓存,使用hashmap作为存储结构。二级缓存还可以使用外部缓存如redis,步骤如下:
    1.业务实体类要实现Serializable接口


    image.png

    2.全局配置与上述一致,map上的配置改为如下:


    image.png

    二级缓存的缺陷-脏数据:
    由于二级缓存是map级别的,通常某一实体对应一个map,包含该实体的增删改查操作,由于关系型数据库的设计,业务查询中经常少不了关联查询,这些查询会根据业务处理规则放在某个map中,map对应二级缓存的更新并不能影响其他map对应的二级缓存,这样就会产生脏数据。

    二级缓存适用场景:
    1.以查询为主的应用,尽可能少的更新操作,对数据实时性要求不高。例如某些统计查询,物流跟踪查询等。
    2.绝大多数单表操作的map,由于没有关联查询,不会有脏数据的问题。

    缺陷解决方案:
    考虑在service层自定义处理缓存(自己维护map或者直接操作redis),代替二级缓存。

    相关文章

      网友评论

          本文标题:mybatis的缓存

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