设为首页 加入收藏

TOP

【源码级】MyBatis缓存策略(一)
2023-07-25 21:23:14 】 浏览:72
Tags:MyBatis

缓存就是内存中的数据,常常来自对数据库查询结果的保存。使用缓存,我们可以避免频繁的与数据库进行交互,进而提高响应速度MyBatis也提供了对缓存的支持,分为一级缓存和二级缓存,可以通过下图来理解:

file
①、一级缓存是SqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。

②、二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的

一级缓存

默认是开启的

①、我们使用同一个sqlSession,对User表根据相同id进行两次查询,查看他们发出sql语句的情况

  @Test
  public void firstLevelCacheTest() throws IOException {

    // 1. 通过类加载器对配置文件进行加载,加载成了字节输入流,存到内存中 注意:配置文件并没有被解析
    InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");

    // 2. (1)解析了配置文件,封装configuration对象 (2)创建了DefaultSqlSessionFactory工厂对象
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

    // 3.问题:openSession()执行逻辑是什么?
    // 3. (1)创建事务对象 (2)创建了执行器对象cachingExecutor (3)创建了DefaultSqlSession对象
    SqlSession sqlSession = sqlSessionFactory.openSession();

    // 4. 委派给Executor来执行,Executor执行时又会调用很多其他组件(参数设置、解析sql的获取,sql的执行、结果集的封装)
    User user = sqlSession.selectOne("com.itheima.mapper.UserMapper.findByCondition", 1);
    User user2 = sqlSession.selectOne("com.itheima.mapper.UserMapper.findByCondition", 1);

    System.out.println(user == user2);

    sqlSession.close();

  }

查看控制台打印情况:

file

② 同样是对user表进行两次查询,只不过两次查询之间进行了一次update操作。

  @Test
  public void test3() throws IOException {

    // 1. 通过类加载器对配置文件进行加载,加载成了字节输入流,存到内存中 注意:配置文件并没有被解析
    InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");

    // 2. (1)解析了配置文件,封装configuration对象 (2)创建了DefaultSqlSessionFactory工厂对象
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

    // 3.问题:openSession()执行逻辑是什么?
    // 3. (1)创建事务对象 (2)创建了执行器对象cachingExecutor (3)创建了DefaultSqlSession对象
    SqlSession sqlSession = sqlSessionFactory.openSession();

    // 4. 委派给Executor来执行,Executor执行时又会调用很多其他组件(参数设置、解析sql的获取,sql的执行、结果集的封装)
    User user = sqlSession.selectOne("com.itheima.mapper.UserMapper.findByCondition", 1);

    User user1 = new User();
    user1.setId(1);
    user1.setUsername("zimu");
    sqlSession.update("com.itheima.mapper.UserMapper.updateUser",user1);
    sqlSession.commit();
    User user2 = sqlSession.selectOne("com.itheima.mapper.UserMapper.findByCondition", 1);

    System.out.println(user == user2);
    System.out.println(user);
    System.out.println(user2);
    System.out.println("MyBatis源码环境搭建成功....");

    sqlSession.close();

  }

查看控制台打印情况:

file

③、总结

1、第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从 数据库查询用户信息。得到用户信息,将用户信息存储到一级缓存中。

2、 如果中间sqlSession去执行commit操作(执行插入、更新、删除),则会清空SqlSession中的 一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。

3、 第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直 接从缓存中获取用户信息

一级缓存原理探究与源码分析

问题1:一级缓存 底层数据结构到底是什么?

问题2:一级缓存的工作流程是怎样的?

一级缓存 底层数据结构到底是什么?

之前说不同SqlSession的一级缓存互不影响,所以我从SqlSession这个类入手

file
可以看到,org.apache.ibatis.session.SqlSession中有一个和缓存有关的方法——clearCache()刷新缓存的方法,点进去,找到它的实现类DefaultSqlSession

  @Override
  public void clearCache() {
    executor.clearLocalCache();
  }

再次点进去executor.clearLocalCache(),再次点进去并找到其实现类BaseExecutor

  @Override
  public void clearLocalCache() {
    if (!closed) {
      localCache.clear();
      localOutputParamet
首页 上一页 1 2 3 4 5 6 7 下一页 尾页 1/9/9
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇java基础-网络编程 下一篇Java五个最常用的集合类之间的区..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目