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 中添加相应的映射
<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,意味着缓存数据只能读取而不能修改,这样设置的好处是可以快速读取缓存,缺点是没有办法修改缓存 |
如果需要对个别查询进行调整,可以单独设置 cache
<select id="getUserInfoList" resultType="com.java265.po.UserInfo" usecache="true"> ... </select>
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。