mybatis-3.4.x 从源码看configuration[笔记二]

mapper sql的映射接口 mybatis的接口是如何与xml的sql关联的
sql映射现在有两种方式

  1. 注解方式
  2. xml配置方法

注册mapper接口

  /*******解析mapper xml 详见XMLMapperBuilder.java*************/
   private void configurationElement(XNode context) {
    try {
      String namespace = context.getStringAttribute("namespace");
      if (namespace == null || namespace.equals("")) {
        throw new BuilderException("Mapper's namespace cannot be empty");
      }
      //设定正在解析的mapper名称空间
      builderAssistant.setCurrentNamespace(namespace);
      /*解析引用的缓存*/
      cacheRefElement(context.evalNode("cache-ref"));
      /*解析自己名称空间的缓存*/
      cacheElement(context.evalNode("cache"));
      /*解析参数映射的map*/
      parameterMapElement(context.evalNodes("/mapper/parameterMap"));
      /*解析结果集映射*/
      resultMapElements(context.evalNodes("/mapper/resultMap"));
      /*解析sql模板*/
      sqlElement(context.evalNodes("/mapper/sql"));
      /*解析增删改查的sql*/
      buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing Mapper XML. The XML location is '" + resource + "'. Cause: " + e, e);
    }
  }

mapper接口执行逻辑分析

  1. mapper 接口MapperProxyFactory生成动态代理对象MapperProxy
  2. MapperProxy 执行接口方法Method 映射的MapperMethod方法获取方法执行结果
  3. MapperMethod对象调用sqlSession对象执行数据库 增删改查操作
  4. sqlSession将操作代理给Executor执行
  5. Executor根据接口映射的MappedStatement对象执行底层数据库操作
  6. MappedStatement 获取sqlSource,并根据参数生成最终的sql语句,GenericTokenParser【${} 直接替换成参数值,#{} 替换成 ?】 解析替换sql内的参数表达式
  7. MappedStatement 获取到Statement ,如果是PreparedStatement,则跟根据参数类型选择合适的typeHandler,为PreparedStatement设置查询的参数值,优先已参数上设置的typeHandler为准,不设置,则自动判断来获取
  8. Statement执行sql,结果集交给ResultSetHandler处理,自动转换成需要的Pojo对象
  9. 获取到结果,如果存在ResultHandler,则交给ResultHandler处理结果
  10. 处理事务,关闭资源

mapper生成代理对象

public class MapperProxyFactory<T> {

  private final Class<T> mapperInterface;
  private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<Method, MapperMethod>();

  public MapperProxyFactory(Class<T> mapperInterface) {
    this.mapperInterface = mapperInterface;
  }

  public Class<T> getMapperInterface() {
    return mapperInterface;
  }

  public Map<Method, MapperMethod> getMethodCache() {
    return methodCache;
  }

  /*获取mapper接口的动态代理对象*/
  @SuppressWarnings("unchecked")
  protected T newInstance(MapperProxy<T> mapperProxy) {
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

  public T newInstance(SqlSession sqlSession) {
    final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
    return newInstance(mapperProxy);
  }

}

代理对象的实际执行逻辑

public class MapperProxy<T> implements InvocationHandler, Serializable {

  private static final long serialVersionUID = -6424540398559729838L;
  private final SqlSession sqlSession;
  private final Class<T> mapperInterface;
  private final Map<Method, MapperMethod> methodCache;

  public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {
    this.sqlSession = sqlSession;
    this.mapperInterface = mapperInterface;
    this.methodCache = methodCache;
  }

  //mapper 接口的实际执行逻辑
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
      //如果是object对象方法则直接调用
      if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, args);
      } else if (isDefaultMethod(method)) {
        //如果是接口默认方法则直接调用
        return invokeDefaultMethod(proxy, method, args);
      }
    } catch (Throwable t) {
      throw ExceptionUtil.unwrapThrowable(t);
    }
    //接口声明的sql映射类方法,执行对应的MapperMethod方法
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    return mapperMethod.execute(sqlSession, args);
  }

  /*方法解析后缓存已解析好的MapperMethod*/
  private MapperMethod cachedMapperMethod(Method method) {
    MapperMethod mapperMethod = methodCache.get(method);
    if (mapperMethod == null) {
      mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());
      methodCache.put(method, mapperMethod);
    }
    return mapperMethod;
  }

  /*调用接口的默认实现*/
  @UsesJava7
  private Object invokeDefaultMethod(Object proxy, Method method, Object[] args)
      throws Throwable {
    final Constructor<MethodHandles.Lookup> constructor = MethodHandles.Lookup.class
        .getDeclaredConstructor(Class.class, int.class);
    if (!constructor.isAccessible()) {
      constructor.setAccessible(true);
    }
    final Class<?> declaringClass = method.getDeclaringClass();
    return constructor
        .newInstance(declaringClass,
            MethodHandles.Lookup.PRIVATE | MethodHandles.Lookup.PROTECTED
                | MethodHandles.Lookup.PACKAGE | MethodHandles.Lookup.PUBLIC)
        .unreflectSpecial(method, declaringClass).bindTo(proxy).invokeWithArguments(args);
  }

  /**
   * Backport of java.lang.reflect.Method#isDefault()
   */
  /*是否默认方法*/
  private boolean isDefaultMethod(Method method) {
    return (method.getModifiers()
        & (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC)) == Modifier.PUBLIC
        && method.getDeclaringClass().isInterface();
  }
}

接口方法映射的MapperMethod,实际的sql执行的路由逻辑,根据SqlCommand方式路由到SqlSession中执行对应的方法

public class MapperMethod {
  //sql的类型 update/delete/insert/select/flush
  private final SqlCommand command;
  //mapper方法的元信息
  private final MethodSignature method;

  public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
    this.command = new SqlCommand(config, mapperInterface, method);
    this.method = new MethodSignature(config, mapperInterface, method);
  }

  public Object execute(SqlSession sqlSession, Object[] args) {
    Object result;
    switch (command.getType()) {
      case INSERT: {
        Object param = method.convertArgsToSqlCommandParam(args);
        result = rowCountResult(sqlSession.insert(command.getName(), param));
        break;
      }
      case UPDATE: {
        Object param = method.convertArgsToSqlCommandParam(args);
        result = rowCountResult(sqlSession.update(command.getName(), param));
        break;
      }
      case DELETE: {
        Object param = method.convertArgsToSqlCommandParam(args);
        result = rowCountResult(sqlSession.delete(command.getName(), param));
        break;
      }
      case SELECT:
        if (method.returnsVoid() && method.hasResultHandler()) {
          //处理带有ResultHandler参数方式的接口
          executeWithResultHandler(sqlSession, args);
          result = null;
        } else if (method.returnsMany()) {
          //处理返回列表类型的接口
          result = executeForMany(sqlSession, args);
        } else if (method.returnsMap()) {
          //处理返回Map集合的接口
          result = executeForMap(sqlSession, args);
        } else if (method.returnsCursor()) {
          //处理返回游标的接口
          result = executeForCursor(sqlSession, args);
        } else {
          //处理只有一条记录返回的接口
          Object param = method.convertArgsToSqlCommandParam(args);
          result = sqlSession.selectOne(command.getName(), param);
        }
        break;
      case FLUSH:
        result = sqlSession.flushStatements();
        break;
      default:
        throw new BindingException("Unknown execution method for: " + command.getName());
    }
    if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
      throw new BindingException("Mapper method '" + command.getName() 
          + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
    }
    return result;
  }
  
  /*
  * INSERT UPDATE  DELETE 返回值只有四种 void,int,long,boolean
  * */
  private Object rowCountResult(int rowCount) {
    final Object result;
    if (method.returnsVoid()) {
      result = null;
    } else if (Integer.class.equals(method.getReturnType()) || Integer.TYPE.equals(method.getReturnType())) {
      result = rowCount;
    } else if (Long.class.equals(method.getReturnType()) || Long.TYPE.equals(method.getReturnType())) {
      result = (long)rowCount;
    } else if (Boolean.class.equals(method.getReturnType()) || Boolean.TYPE.equals(method.getReturnType())) {
      result = rowCount > 0;
    } else {
      throw new BindingException("Mapper method '" + command.getName() + "' has an unsupported return type: " + method.getReturnType());
    }
    return result;
  }
  ...
public static class MethodSignature {
    //是否返回多条记录
    private final boolean returnsMany;
    //是否返回map
    private final boolean returnsMap;
    //是否没有返回值
    private final boolean returnsVoid;
    //是否返回游标
    private final boolean returnsCursor;
    //返回类型
    private final Class<?> returnType;
    //返回值为Map是作为key的属性
    private final String mapKey;
    //resultHandler参数的参数索引位置
    private final Integer resultHandlerIndex;
    //rowBounds参数的参数索引位置
    private final Integer rowBoundsIndex;
    //参数名称解析实现类
    private final ParamNameResolver paramNameResolver;

    public MethodSignature(Configuration configuration, Class<?> mapperInterface, Method method) {
      Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, mapperInterface);
      if (resolvedReturnType instanceof Class<?>) {
        this.returnType = (Class<?>) resolvedReturnType;
      } else if (resolvedReturnType instanceof ParameterizedType) {
        this.returnType = (Class<?>) ((ParameterizedType) resolvedReturnType).getRawType();
      } else {
        this.returnType = method.getReturnType();
      }
      this.returnsVoid = void.class.equals(this.returnType);
      this.returnsMany = configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray();
      this.returnsCursor = Cursor.class.equals(this.returnType);
      this.mapKey = getMapKey(method);
      this.returnsMap = this.mapKey != null;
      this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);
      this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);
      this.paramNameResolver = new ParamNameResolver(configuration, method);
    }
    ...

sqlSession 根据commandName获取到对应的MappedStatement,交给executor执行

public final class MappedStatement {
  //资源文件
  private String resource;
  //核心配置类
  private Configuration configuration;
  //唯一标识
  private String id;
  //sql设置的fetchSize
  private Integer fetchSize;
  private Integer timeout;
  //Statement 类型
  private StatementType statementType;
  private ResultSetType resultSetType;
  //sql的信息
  private SqlSource sqlSource;
  //对应的缓存地址
  private Cache cache;
  //配置的参数映射集合
  private ParameterMap parameterMap;
  //结果集映射
  private List<ResultMap> resultMaps;
  //是否刷新缓存
  private boolean flushCacheRequired;
  //是否使用缓存
  private boolean useCache;
  private boolean resultOrdered;
  //sql的类型
  private SqlCommandType sqlCommandType;
  //主键生成策略
  private KeyGenerator keyGenerator;
  private String[] keyProperties;
  private String[] keyColumns;
  private boolean hasNestedResultMaps;
  private String databaseId;
  private Log statementLog;
  private LanguageDriver lang;
  private String[] resultSets;
  ...

executor查询

  /*详见BaseExecutor.java*/
  @Override
  public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
    //根据参数获取需要执行的sql
    BoundSql boundSql = ms.getBoundSql(parameter);
    CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
    return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
 }
 /***详见MappedStatement.java***/
  public BoundSql getBoundSql(Object parameterObject) {
    //根据参数获取需要执行的sql,将${},#{}处理掉,处理掉条件语句,组装成最终的SQL
    BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    if (parameterMappings == null || parameterMappings.isEmpty()) {
      boundSql = new BoundSql(configuration, boundSql.getSql(), parameterMap.getParameterMappings(), parameterObject);
    }

    // check for nested result maps in parameter mappings (issue #30)
    for (ParameterMapping pm : boundSql.getParameterMappings()) {
      String rmId = pm.getResultMapId();
      if (rmId != null) {
        ResultMap rm = configuration.getResultMap(rmId);
        if (rm != null) {
          hasNestedResultMaps |= rm.hasNestedResultMaps();
        }
      }
    }

    return boundSql;
  }
/*详见CachingExecutor.java*/
@Override
  public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
      throws SQLException {
    //获取mapper对应的缓存
    Cache cache = ms.getCache();
    if (cache != null) {
      //如果需要刷新缓存就清掉二级缓存
      flushCacheIfRequired(ms);
      //如果使用缓存,且没有resultHandler则先试着从缓存读取结果
      if (ms.isUseCache() && resultHandler == null) {
        ensureNoOutParams(ms, boundSql);
        @SuppressWarnings("unchecked")
        List<E> list = (List<E>) tcm.getObject(cache, key);
        if (list == null) {
          //没有缓存,则执行后面的代理操作
          list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
          tcm.putObject(cache, key, list); // issue #578 and #116
        }
        return list;
      }
    }
    return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }
/*详见BaseExecutor.java*/
  @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()) {
      clearLocalCache();
    }
    List<E> list;
    try {
      queryStack++;
      //从一级缓存读取查询结果
      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);
      }
    } finally {
      queryStack--;
    }
    if (queryStack == 0) {
      for (DeferredLoad deferredLoad : deferredLoads) {
        deferredLoad.load();
      }
      // issue #601
      deferredLoads.clear();
      //如果LocalCacheScope为STATEMENT,则不缓存
      if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
        // issue #482
        clearLocalCache();
      }
    }
    return list;
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值