Mybatis一级缓存、二级缓存

一、概述
像大多数的持久化框架一样,Mybatis 也提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提高性能。Mybatis 中缓存分为一级缓存,二级缓存。

二、一级缓存
一级缓存是 SqlSession 级别的缓存,只要 SqlSession 没有 flush 或 close,它就存在。
证明一级缓存的存在:
1.编写持久层接口

/**
 * 根据id查询用户信息
 * @param userId
 * @return
 */
User findUserById(Integer userId);

2.编写持久层映射文件 userMapper.xml

<mapper namespace="com.itheima.dao.IUserDao">
<!-- 根据 id 查询 --> <select id="findById" resultType="UsEr" parameterType="int" useCache="true">
select * from user where id = #{uid}
</select>
</mapper>

3.编写测试方法

import com.mrhan.dao.IUserDao;
import com.mrhan.entity.User;
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.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.InputStream;

public class UserTest {
    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession session;
    private IUserDao userDao;


    @Before
    public void init() throws Exception {
        //1.读取配置文件
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.构建者对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //3.创建SqlSession工厂对象
        factory = builder.build(in);
        //4.创建SqlSession对象
        session = factory.openSession(true);
        //5.创建Dao代理对象
        userDao = session.getMapper(IUserDao.class);
    }


    @After
    public void destroy() throws  Exception{
        //session.commit();
        //7.释放资源
        session.close();
        in.close();
    }

    @Test
    public void testFindById(){
        //6.查询
        User user = userDao.findUserById(1);
        System.out.println("第一次查询的用户:"+user);
        User user2 = userDao.findUserById(1);
        System.out.println("第二次查询的用户:"+user2);
    }

4.测试结果如下:
在这里插入图片描述

可以看到,虽然上述代码查询了两次,但最后只执行了一次数据库操作,
这就是Mybatis一级缓存起作用了,第二次查询并没有通过sql语句从数据库中查询数据,而是从一级缓存中查询

5.一级缓存分析:
第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询,并将其存储到一级缓存中
如果sqlsession去执行commit(插入更新删除时)
清空sqlsession一级缓存,这样做的目的是为了让缓存 中存储的是最新的消息 避免藏独
第二次发起查询,如果缓存中有 则直接从缓存中获取用户信息

三、Mybatis二级缓存
二级缓存是mapper 映射级别的缓存 多个SqlSession 去操作同一个mapper映射的sql语句
多个Sqlsession可以共用二级缓存 二级缓存是跨SqlSession的

  1. 在主配置文件mybatisConfig.xml中开启二级缓存
<settings>
<!-- 开启二级缓存的支持 --> <setting name="cacheEnabled" value="true"/>
</settings>

因为 cacheEnabled 的取值默认就为 true,所以这一步可以省略不配置。为 true 代表开启二级缓存;为false 代表不开启二级缓存。

2.配置Mapper映射文件

<cache>标签表示当前这个 mapper 映射将使用二级缓存,区分的标准就看 mapper 的 namespace 值。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper 
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.itheima.dao.IUserDao">
<!-- 开启二级缓存的支持 -->
<cache></cache>
</mapper>
<!-- 根据 id 查询 --> <select id="findById" resultType="user" parameterType="int" useCache="true">
select * from user where id = #{uid}
</select> 将 UserDao.xml 映射文件中的<select>标签中设置 useCache=true”代表当前这个 statement 要使用
二级缓存,如果不使用二级缓存可以设置为 false。
注意:针对每次查询都需要最新的数据 sql,要设置成 useCache=false,禁用二级缓存

3、二级缓存测试

@Before//用于在测试方法执行之前执行
 public void init()throws Exception{
 //1.读取配置文件,生成字节输入流
 in = Resources.getResourceAsStream("SqlMapConfig.xml");
 //2.获取 SqlSessionFactory
 factory = new SqlSessionFactoryBuilder().build(in);
 }
 @After//用于在测试方法执行之后执行
 public void destroy()throws Exception{
 in.close();
 }

 @Test
 public void testFirstLevelCache(){
 SqlSession sqlSession1 = factory.openSession();
 IUserDao dao1 = sqlSession1.getMapper(IUserDao.class);
 User user1 = dao1.findById(1);
 System.out.println(user1);
 sqlSession1.close();//一级缓存消失
 SqlSession sqlSession2 = factory.openSession();
 IUserDao dao2 = sqlSession2.getMapper(IUserDao.class);
 User user2 = dao2.findById(1);
 System.out.println(user2);
 sqlSession2.close();
 System.out.println(user1 == user2);
 }

经过测试,我们发现执行了两次查询,并且在执行第一次查询后,我们关闭了以及缓存,再去执行第二次查询时,比我们发现并没有对数据库进行sql查询 所以此时的数据只能来自于我们所说的二级缓存

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值