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

Java-框架王 MyBatis 发布时间:2021-07-21 09:45:40 阅读数:14069 1

缓存简介

缓存的功能是将数据存储到内存中,
是我们日常开发中常用的操作方式,常见的专用缓存服务器有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 中添加相应的映射

<select id="selectUserInfoById"
    resultType="com.java265.po.UserInfo">
    SELECT * FROM UserInfo
    WHERE id=#{id}
</select>

测试代码
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
<settings>
    <setting name="cacheEnabled" value="true" />
</settings>
2.在mapper文件(如 WebMapper.xml)中设置缓存,默认不开启缓存
需要注意的是,二级缓存的作用域是针对 mapper 的 namescape 而言
即只有再次在 namescape 内(com.java265.UserInfoMapper)的查询才能共享这个缓存

<mapper namescape="com.java265.UserInfoMapper">
    <!-- cache配置 -->
    <cache
        eviction="FIFO"
        flushInterval="60000"
        size="512"
        readOnly="true" />
    ...
</mapper>

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

 <select id="getUserInfoList" resultType="com.java265.po.UserInfo" usecache="true">
    ...
</select>

版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

本文链接: https://www.Java265.com/JavaFramework/MyBatis/202107/555.html

最近发表

热门文章

好文推荐

Java265.com

https://www.java265.com

站长统计|粤ICP备14097017号-3

Powered By Java265.com信息维护小组

使用手机扫描二维码

关注我们看更多资讯

java爱好者