mybatis源码-第二部分-工厂创建产品

一丶工厂获取产品 
 源码部分: 
 

DefaultSqlSession 类
@Override
  public <T> T selectOne(String statement) {
    return this.<T>selectOne(statement, null);
  }

@Override
    public <T> T selectOne(String statement, Object parameter) {
    // Popular vote was to return null on 0 results and throw exception on too many.
    List<T> list = this.<T>selectList(statement, parameter);
    if (list.size() == 1) { //通过list.size()来进行判断,当=1的时候返回结果,大于1的时候抛出异常。
      return list.get(0);
    } else if (list.size() > 1) {
      throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
    } else {
      return null;
    }
  }
  
@Override
    public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
      try {
        MappedStatement ms = configuration.getMappedStatement(statement);// 返回数据库执行语句
        return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
      } catch (Exception e) {
        throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
      } finally {
        ErrorContext.instance().reset();
      }
    }
    
    //query 中的核心
    @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.");
        }
        if (queryStack == 0  ms.isFlushCacheRequired()) { //当计数器为0 且为需要刷新缓存的时候
          clearLocalCache();//清空本地缓存
        }
        List<E> list;
        try {
          queryStack++;         //计数器+1
          list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;当为null时,先从本地的缓存中去取
          if (list != null) { //取到了对象
            handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);//对相同的语句进行优化,之前有,而且没有需要刷新缓存还存在的数据
          } else {
            list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);//实在没有那就在查一次
          }
        } finally {
          queryStack--;
        }
        if (queryStack == 0) {  //当计数器为0,循环从本地缓存中查找
          for (DeferredLoad deferredLoad : deferredLoads) {
            deferredLoad.load();
          }
          // issue #601
          deferredLoads.clear();
          if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) { //作用于为sql的时候,清空本地缓存
            // issue #482
            clearLocalCache();
          }
        }
        return list;
      }
      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); //做一个占位符,将本地缓存,用对应的key占位
          try {
            list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);//查询返回list
          } finally {
            localCache.removeObject(key);       //将刚才占位的移除
          }
          localCache.putObject(key, list);      //添加真正的本地缓存
          if (ms.getStatementType() == StatementType.CALLABLE) { //如果配置文件开启了缓存,把这个结果放入一级缓存
            localOutputParameterCache.putObject(key, parameter);
          }
          return list;
        }
    
    public MappedStatement getMappedStatement(String id, boolean validateIncompleteStatements) {
        if (validateIncompleteStatements) {
          buildAllStatements();
        }
        return mappedStatements.get(id);// 传入mapper类路径,在建立工厂的时候,已经将代理工厂作为value,类名作为key
        //方法如下:
        这边put方法的思路很清晰,第一步判断是否存在key,如果已经存在抛出异常,否则将传入的mapper路径通过getShortName截取到.后面的字符串
        //Ambiguity这个类其实就是一个字符串。
        //当Ambiguity抛异常就表面有两个id相同的sql语句,mybatis不知道要执行哪一个了,所以异常了。
        //在这边放入value,在get方法取出时value instanceof Ambiguity 来校验
        @SuppressWarnings("unchecked")
                         public V put(String key, V value) {
                           if (containsKey(key)) {
                             throw new IllegalArgumentException(name + " already contains value for " + key);
                           }
                           if (key.contains(".")) {
                             final String shortKey = getShortName(key);
                             if (super.get(shortKey) == null) {
                               super.put(shortKey, value);
                             } else {
                               super.put(shortKey, (V) new Ambiguity(shortKey));
                             }
                           }
                           return super.put(key, value);
                         }
      }
      //
      public V get(Object key) {
            V value = super.get(key);
            if (value == null) {
              throw new IllegalArgumentException(name + " does not contain value for " + key);
            }
            if (value instanceof Ambiguity) {
              throw new IllegalArgumentException(((Ambiguity) value).getSubject() + " is ambiguous in " + name
                  + " (try using the full name including the namespace, or rename one of the entries)");
            }
            return value;
          }
          
    // mappedStatements是被Configuration类中new StrictMap出来的
  protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection");
    //与map不一样他多了 name
      public StrictMap(String name, Map<String, ? extends V> m) {
           super(m);
           this.name = name;
         }

总体思路:
1.工厂生成产品,返回默认的产品,这些产品也和工厂一样,不同的配置生成出不一样的产品。

2.默认产品实现SqlSession接口下的某得接口,例如selectOne接口,通过selectList,返回list,当个数为一返回结果。

3.selectList方法,通过getMappedStatement返回执行语句,调用核心的executor.query()方法,这个方法主要就是有缓存,从缓存去,没有缓存,再查询。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值