• mybatis缓存


    执行sql,需用SqlSession,就类似jdbc
    jdbc:
    1.获取驱动 Drever.get(XXXX);
    2.获取链接connection;
    3.statement,prestatement进行sql语句与参数拼装
    4.到数据库执行
    5.ResultSet返回,
    6.实体映射封装返回
    
    
    mybatis其实就是把statement,prestatement给封装了下
    mybatis:
    1.执行器Executor:SQL执行过程的总体控制
    2、StatementHandler:语句处理器负责和JDBC层具体交互,包括prepare语句,执行语句
    3、ParameterHandler:参数处理器负责PreparedStatement入参的具体设置
    4、ResultSetHandler:结果处理器负责将JDBC查询结果映射到java对象
    
    tips:二级缓存放在了Map里面
    详情看下面的源码
    

     

     

    以下是mybatis源码:
    
      @Override
      public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
        BoundSql boundSql = ms.getBoundSql(parameter);
        //创建一级缓存
        CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
        return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
      }
    
    @Override
      public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
       //判断执行器是否关闭   
     if (closed) {
          throw new ExecutorException("Executor was closed.");
        }
        CacheKey cacheKey = new CacheKey();
    //1、将Statement中的id添加到CacheKey对象中的updateList属性  ,这个ID是某个方法所在的dAO(持久层方法全路径)
        cacheKey.update(ms.getId());
    //2、将offset(分页偏移量)添加到CacheKey对象中的updateList属性(如果没有分页则默认0)
        cacheKey.update(rowBounds.getOffset());
    //3、将limit(每页显示的条数)添加到CacheKey对象中的updateList属性(如果没有分页则默认Integer.MAX_VALUE)
        cacheKey.update(rowBounds.getLimit());
    //4、将sql语句(包括占位符?)添加到CacheKey对象中的updateList属性
        cacheKey.update(boundSql.getSql());
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();
        // mimic DefaultParameterHandler logic
    //5、循环用户传入的参数,并将每个参数添加到CacheKey对象中的updateList属性
        for (ParameterMapping parameterMapping : parameterMappings) {
          if (parameterMapping.getMode() != ParameterMode.OUT) {
            Object value;
            String propertyName = parameterMapping.getProperty();
            if (boundSql.hasAdditionalParameter(propertyName)) {
              value = boundSql.getAdditionalParameter(propertyName);
            } else if (parameterObject == null) {
              value = null;
            } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
              value = parameterObject;
            } else {
              MetaObject metaObject = configuration.newMetaObject(parameterObject);
              value = metaObject.getValue(propertyName);
            }
            cacheKey.update(value);
          }
        }
        if (configuration.getEnvironment() != null) {
          // issue #176  
    //6、如果有配置Environment,则将Environment中的id添加到CacheKey对象中的updateList属性
          cacheKey.update(configuration.getEnvironment().getId());
        }
        return cacheKey;
      }
    
      @SuppressWarnings("unchecked")
      @Override
      public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
        ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
     //执行器关闭
        if (closed) {
          throw new ExecutorException("Executor was closed.");
        }
    //查询次数为0,或者需要清除缓存属性为true:清楚本地缓存(一级缓存)
        if (queryStack == 0 && ms.isFlushCacheRequired()) {
          clearLocalCache();
        }
        List<E> list;
        try {
          queryStack++;
    //结果处理器为空,从缓存获取
          list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
          if (list != null) {
     //缓存list不为空,从缓存获取
            handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
          } else {
    //(一级缓存)本地缓存为空,从数据库获取
            list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
          }
        } finally {
          queryStack--;
        }
        if (queryStack == 0) {
          for (DeferredLoad deferredLoad : deferredLoads) {
            deferredLoad.load();
          }
          // issue #601
          deferredLoads.clear();
          if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
            // issue #482
            clearLocalCache();
          }
        }
        return list;
      }
    
    //缓存获取  对应://缓存list不为空,从缓存获取
      private void handleLocallyCachedOutputParameters(MappedStatement ms, CacheKey key, Object parameter, BoundSql boundSql) {
        if (ms.getStatementType() == StatementType.CALLABLE) {
          final Object cachedParameter = localOutputParameterCache.getObject(key);
          if (cachedParameter != null && parameter != null) {
            final MetaObject metaCachedParameter = configuration.newMetaObject(cachedParameter);
            final MetaObject metaParameter = configuration.newMetaObject(parameter);
            for (ParameterMapping parameterMapping : boundSql.getParameterMappings()) {
              if (parameterMapping.getMode() != ParameterMode.IN) {
                final String parameterName = parameterMapping.getProperty();
                final Object cachedValue = metaCachedParameter.getValue(parameterName);
                metaParameter.setValue(parameterName, cachedValue);
              }
            }
          }
        }
      }
    
    //从数据库获取
      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);
        if (ms.getStatementType() == StatementType.CALLABLE) {
    //放入Map
          localOutputParameterCache.putObject(key, parameter);
        }
        return list;
      }
    
     
    解释数据库里面那个localOutputParameterCache参数,这个参数最终操作是放入Map
     protected PerpetualCache localOutputParameterCache;
     @Override
      public void putObject(Object key, Object value) {
        cache.put(key, value);
      }
      private final Map<Object, Object> cache = new HashMap<>();
    
  • 相关阅读:
    Linux学习第一天:SecureCRT连接Linux常见错误
    函数
    文件a.txt内容:每一行内容分别为商品名字,价钱,个数,求出本次购物花费的总钱数
    文件处理
    自定义函数
    三级菜单
    写一个循环,不断的问客户想买什么 ,当用户选择一个商品编号,就把对应的商品加入购物车 ,最终用户输入q退出时,答应购物车的商品
    9*9乘法表
    打印列表的每个元素和索引值
    names里面有3个2,返回第2个2的索引值
  • 原文地址:https://www.cnblogs.com/wangbiaohistory/p/15817554.html
Copyright © 2020-2023  润新知