• Mybatis 一级缓存


    介绍

    Mybatis 默认开启一级缓存,一级缓存只是相对于同一个 SqlSession 而言。所以在参数完全一样的情况下,我们使用同一个 SqlSession 对象连续调用同一个 Mapper 方法,往往只执行一次SQL。

    读取缓存数据

    main 方法

    public class Test {
      public static void main(String[] args) throws Exception {
        String resource = "SqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session = factory.openSession();
        // 查询方法
        Object obj = session.selectOne("com.dao.UserMapper.findUserById", 2);
        System.out.println(obj.toString());
        session.close();
      }
    }
    

    DefaultSqlSession selectOne 方法

      public <T> T selectOne(String statement, Object parameter) {
        // 调用 selectList 方法
        List<T> list = this.<T>selectList(statement, parameter);
        if (list.size() == 1) {
          return list.get(0);
        } 
      }
    

    DefaultSqlSession selectList 方法

      public <E> List<E> selectList(String statement, Object parameter) {
        // 调用重载方法
        return this.selectList(statement, parameter, RowBounds.DEFAULT);
      }
    
      public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
        MappedStatement ms = configuration.getMappedStatement(statement);
        // 执行器查询
        return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
      }
    }
    

    BaseExecutor query 方法

      // 一级缓存器
      protected PerpetualCache localCache;
    
      public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, 
                                                                           ResultHandler resultHandler){
        BoundSql boundSql = ms.getBoundSql(parameter);
        CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
        // 重载方法
        return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
      }
    
      public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, 
                                         ResultHandler resultHandler, CacheKey key, BoundSql boundSql){
        List<E> list;
        // 一级缓存中取数据
        list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
        if (list != null) {
          handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
        } else {
          // 查询数据库
          list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
        }
        return list;
      }
    

    PerpetualCache getObject 方法

      //一级缓存的本质就是一个 HashMap
      private final Map<Object, Object> cache = new HashMap();
    
      public Object getObject(Object key) {
        return this.cache.get(key);
      }
    

    缓存数据

    BaseExecutor queryFromDatabase 方法

      private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, 
                     ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
        List<E> list;
        localCache.putObject(key, EXECUTION_PLACEHOLDER);
        try {
          list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
        } finally {
          localCache.removeObject(key);
        }
        // 缓存数据
        localCache.putObject(key, list);
        return list;
      }
    
  • 相关阅读:
    js三种存储方式区别
    利用split方法计算字符串中出现字母最多的次数
    图片预加载的三个方法
    页面有大量图片,优化图片的加载方法
    USB通信协议——深入理解
    C/C++回调函数
    显卡工作原理
    include包含头文件的语句中,双引号和尖括号的区别是什么?
    华为2015校园招聘 上机试题
    位操作基础篇之位操作全面总结
  • 原文地址:https://www.cnblogs.com/feiqiangsheng/p/15890658.html
Copyright © 2020-2023  润新知