• MyBatis 如何实现缓存(一级缓存和二级缓存)呢?


    转自:

    MyBatis 如何实现缓存(一级缓存和二级缓存)呢?

    缓存简介

    缓存的功能是将数据存储到内存中,
    是我们日常开发中常用的操作方式,常见的专用缓存服务器有MongoDB、Redis、Ehcache 等
    缓存具有读取速度快的特点,所以被大量应用于系统之中

    MyBatis的缓存分为:
    一级缓存和二级缓存,下文将着重讲述两种缓存的应用,如下所示:

    一级缓存

    一级缓存是MyBatis自带的缓存方式,它的作用域为Session域内
    当 session flush(刷新)或者 close(关闭)之后
    该 session 中所有的 cache(缓存)就会被清空
    当参数和SQL完全一样的情况下,
    我们使用同一个 SqlSession 对象调用同一个 mapper 的方法,往往只执行一次 SQL
    出现这种现象的原因就是MyBatis的一级缓存,
    当使用SqlSession第一次查询后,
    MyBatis 会将查询结果放在缓存中,当我们再一次查询时,如果此时不刷新sqlsession时,则会返回缓存中的结果,而不会去数据库中读取数据

    注意事项:
        SqlSession是相互隔离的
    当我们使用不同的SqlSession对象
    即使调用相同的 Mapper、参数和方法,
    MyBatis也会再次向数据库发送SQL,并使用数据库返回的结果
    

    例 在UserInfoMapper 类中添加 selectUserInfoById 方法,代码如下

    public UserInfo selectUserInfoById(int id);
    

    UserInfoMapper.xml 中添加相应的映射

    
    
    

    测试代码

    package com.java265.test;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.apache.log4j.Logger;
    import com.java265.po.UserInfo;
    
    public class Test {
        public static Logger logger = Logger.getLogger(Test.class);
        public static void main(String[] args) throws IOException {
            InputStream config = Resources.getResourceAsStream("mybatis-config.xml"); // 根据配置文件构建
            SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(config);
            SqlSession ss1 = ssf.openSession();
            UserInfo user1 = ss1.selectOne("com.java265.mapper.UserInfoMapper.selectUserInfoById", 1);
            logger.debug("使用同一个sqlsession再执行一次");
            UserInfo user2 = ss1.selectOne("com.java265.mapper.UserInfoMapper.selectUserInfoById", 1);
            // 请注意,当我们使用二级缓存的时候,sqlSession调用了 commit方法后才会生效
            ss.commit();
            logger.debug("现在创建一个新的SqlSeesion对象在执行一次");
            SqlSession ss2 = ssf.openSession();
            UserInfo user3 = ss2.selectOne("com.java265.mapper.UserInfoMapper.selectUserInfoById", 1);
            // 请注意,当我们使用二级缓存的时候,sqlSession调用了 commit方法后才会生效
            ss2.commit();
        }
    }
    

    运行结果
    DEBUG [main] - ==> Preparing: SELECT * FROM UserInfo WHERE id=?
    DEBUG [main] - ==> Parameters: 1(Integer)
    DEBUG [main] - <== Total: 1
    DEBUG [main] - 使用同一个sqlsession再执行一次
    DEBUG [main] - 现在创建一个新的SqlSeesion对象在执行一次
    DEBUG [main] - ==> Preparing: SELECT * FROM UserInfo WHERE id=?
    DEBUG [main] - ==> Parameters: 1(Integer)
    DEBUG [main] - <== Total: 1

    从以上的输出信息,我们可以看出 “ss1” 只进行过一次查询操作,
    这就是MyBatis一级缓存的效果
    

    二级缓存

    二级缓存是全局缓存,其缓存数据的作用范围超出session范围之外,其缓存数据可以被所有Sqlsession共享

    一级缓存缓存内容为SQL 语句
    二级缓存缓存内容为结果对象
    

    二级缓存的配置方法

    1.MyBatis 的全局缓存配置需要在 mybatis-config.xml 的 settings

    
        
    
    

    2.在mapper文件(如 WebMapper.xml)中设置缓存,默认不开启缓存
    需要注意的是,二级缓存的作用域是针对 mapper 的 namescape 而言
    即只有再次在 namescape 内(com.java265.UserInfoMapper)的查询才能共享这个缓存

    
        
        
        ...
    
    
    

    属性备注说明
    eviction代表的是缓存回收策略,目前 MyBatis 提供以下策略
    LRU使用较少,移除最长时间不用的对象
    FIFO先进先出,按对象进入缓存的顺序来移除它们
    SOFT软引用,移除基于垃圾回收器状态和软引用规则的对象
    WEAK弱引用,更积极地移除基于垃圾收集器状态和弱引用规则的对象
    flushInterval刷新间隔时间,单位为毫秒,这里配置的是 100 秒刷新,如果省略该配置,那么只有当 SQL 被执行的时候才会刷新缓存
    size引用数目,正整数,代表缓存最多可以存储多少个对象,不宜设置过大。设置过大会导致内存溢出。这里配置的是 1024 个对象
    readOnly只读,默认值为 false,意味着缓存数据只能读取而不能修改,这样设置的好处是可以快速读取缓存,缺点是没有办法修改缓存

    3)在 mapper 文件配置支持 cache 后
    如果需要对个别查询进行调整,可以单独设置 cache

     
    
  • 相关阅读:
    CentOS 7 离线安装nginx1.18
    非关系型数据库技术课程 第三周作业(Redis中的订阅与发布、事务机制、集合(set)数据类型实验)
    iOS开发-WKWebView加载微信H5支付
    计算机视觉处理的开源框架
    自定义输入密码控件
    Docker安装部署,拉取镜像-详细过程
    测试和验证有什么区别,怎么划分测试集和验证集
    go实现剑指offer
    【SemiDrive源码分析】【X9芯片启动流程】32 - DisPlay模块分析 - RTOS侧
    经验之谈:内存泄露的原因以及分析
  • 原文地址:https://blog.csdn.net/qq_25073223/article/details/128073021