阅读代码深入原理20——MyBatis之ORM

阅读代码深入原理20——MyBatis之ORMMyBatis被认为是一个半自动ORM框架,SQL是使用者写的,java对象转关系型数据库查询变量和关系转java对象由MyBatis实现。先看

欢迎大家来到IT世界,在知识的湖畔探索吧!

MyBatis被认为是一个半自动ORM框架,SQL是使用者写的,java对象转关系型数据库查询变量和关系转java对象由MyBatis实现。

先看结果集的处理,回到上次的getRowValue的创建对象:

# mybatis-3.5.7.jar!/org.apache.ibatis.executor.resultset.DefaultResultSetHandler
  private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {
    final ResultLoaderMap lazyLoader = new ResultLoaderMap();
    Object rowValue = createResultObject(rsw, resultMap, lazyLoader, columnPrefix); // 一、创建空对象
    if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
      final MetaObject metaObject = configuration.newMetaObject(rowValue); // 二、一般没有java bean对应的TypeHandler,创建MetaObject包装空对象
      boolean foundValues = this.useConstructorMappings;
      if (shouldApplyAutomaticMappings(resultMap, false)) { 
        foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues; // 三、ResultMap.autoMapping为null,Configuration.autoMappingBehavior不为null,但ResultSetWrapper.unMappedColumnNamesMap为空,不处理
      }
      foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues; // 四、无论result元素使用resultType还是resultMap,propertyResultMappings不为空,从ResultSetWrapper里获取ResultSet,再使用TypeHandler获取列对应的值
      foundValues = lazyLoader.size() > 0 || foundValues;
      rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;
    }
    return rowValue;
  }  
  private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {
    this.useConstructorMappings = false; // reset previous mapping result
    final List<Class<?>> constructorArgTypes = new ArrayList<>();
    final List<Object> constructorArgs = new ArrayList<>();
    Object resultObject = createResultObject(rsw, resultMap, constructorArgTypes, constructorArgs, columnPrefix); // a. 创建空对象
    if (resultObject != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) { // b. result使用resultType或resultMap会有propertyMappings
      final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
      for (ResultMapping propertyMapping : propertyMappings) {
        // issue gcode #109 && issue #149
        if (propertyMapping.getNestedQueryId() != null && propertyMapping.isLazy()) { // c. 有子查询且属性懒加载时使用代理对象
          resultObject = configuration.getProxyFactory().createProxy(resultObject, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);
          break;
        }
      }
    }
    this.useConstructorMappings = resultObject != null && !constructorArgTypes.isEmpty(); // set current mapping result
    return resultObject;
  }
  
  private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, List<Class<?>> constructorArgTypes, List<Object> constructorArgs, String columnPrefix)
      throws SQLException {
    final Class<?> resultType = resultMap.getType(); // 1. 取result元素的type属性
    final MetaClass metaType = MetaClass.forClass(resultType, reflectorFactory); // 2. 取Configuration的reflectorFactory(默认为DefaultReflectionFactory),创建MetaClass
    final List<ResultMapping> constructorMappings = resultMap.getConstructorResultMappings(); // 3. 取result元素的constructor子元素
    if (hasTypeHandlerForResultObject(rsw, resultType)) {
      return createPrimitiveResultObject(rsw, resultMap, columnPrefix); // 4. 列类型存在TypeHandler时,使用TypeHandler处理指定列
    } else if (!constructorMappings.isEmpty()) {
      return createParameterizedResultObject(rsw, resultType, constructorMappings, constructorArgTypes, constructorArgs, columnPrefix); // 5. 使用TypeHandler获取列的值(有内嵌查询则获取内嵌查询结果),使用ObjectFactory根据构造函数类型创建JAVA对象
    } else if (resultType.isInterface() || metaType.hasDefaultConstructor()) {
      return objectFactory.create(resultType); // 6. 如果是Map或集合接口,则指定默认实现类型,或有默认构造函数的,使用构造函数创建对象
    } else if (shouldApplyAutomaticMappings(resultMap, false)) {
      return createByConstructorSignature(rsw, resultType, constructorArgTypes, constructorArgs); // 6. 只有1个构造函数或者构造函数有@AutomapConstructor注解的被认为是默认构造函数,使用ObjectFactory创建对象;否则从所有构造函数里挑选有TypeHandler的构造函数创建对象
    }
    throw new ExecutorException("Do not know how to create an instance of " + resultType);
  }  
  
  private boolean applyPropertyMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, ResultLoaderMap lazyLoader, String columnPrefix)
      throws SQLException {
    final List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix); // 1. 从ResultMap.mappedColumns取出映射的列名
    boolean foundValues = false;
    final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings(); // 2. 取propertyResultMappings
    for (ResultMapping propertyMapping : propertyMappings) {
      String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);
      if (propertyMapping.getNestedResultMapId() != null) { // 3. 有子结果集的先将column置为null
        // the user added a column attribute to a nested result map, ignore it
        column = null;
      }
      if (propertyMapping.isCompositeResult()
          || (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH)))
          || propertyMapping.getResultSet() != null) {
        Object value = getPropertyMappingValue(rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix); // 4. 有子结果集的处理子结果集,已有结果的返回延迟对象,一般情况使用TypeHandler从ResultSet获取对应列的值
        // issue #541 make property optional
        final String property = propertyMapping.getProperty();
        if (property == null) {
          continue;
        } else if (value == DEFERRED) { // 5. propertyMapping.resultSet不为null的暂不设置
          foundValues = true;
          continue;
        }
        if (value != null) {
          foundValues = true;
        }
        if (value != null || (configuration.isCallSettersOnNulls() && !metaObject.getSetterType(property).isPrimitive())) {
          // gcode issue #377, call setter on nulls (value is not 'found')
          metaObject.setValue(property, value); // 6. 设置值
        }
      }
    }
    return foundValues;
  }  

欢迎大家来到IT世界,在知识的湖畔探索吧!

有反射经验的小伙伴,估计以为是直接反射调用setter方法了。那是否真的如此呢?我们接着看MetaObject的处理:

欢迎大家来到IT世界,在知识的湖畔探索吧!# mybatis-3.5.7.jar!/org.apache.ibatis.reflection.MetaObject
  public void setValue(String name, Object value) {
    PropertyTokenizer prop = new PropertyTokenizer(name); // 1. 属性可能是复杂对象,需要再解析属性名:有"."则代表属性有子属性,有"["则代表是数组或集合对象
    if (prop.hasNext()) {
      MetaObject metaValue = metaObjectForProperty(prop.getIndexedName()); // 2. 取切割后的属性,尝试从ObjectWrapper获取值
      if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
        if (value == null) {
          // don't instantiate child path if value is null
          return;
        } else {
          metaValue = objectWrapper.instantiatePropertyValue(name, prop, objectFactory); // 3. 包装对象为占位对象且真实对象不为null,根据属性类型创建空对象
        }
      }
      metaValue.setValue(prop.getChildren(), value); // 4. 设置子属性的值
    } else {
      objectWrapper.set(prop, value); // 5. 更新ObjectWrapper中对应属性的值(一般pojo对象是此步骤),ObjectWrapper会根据对象的不同而不同,比如ObjectWrapper、MapWrapper、CollectionWrapper、BeanWrapper等
    }
  }
  
  public MetaObject metaObjectForProperty(String name) {
    Object value = getValue(name); // 2.1 取值
    return MetaObject.forObject(value, objectFactory, objectWrapperFactory, reflectorFactory); // 2.2 创建新的包装对象
  }
  public Object getValue(String name) {
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (prop.hasNext()) {
      MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
      if (metaValue == SystemMetaObject.NULL_META_OBJECT) {  // 2.1.1 将属性从最细粒度往上获取,如果为占位对象,返回null
        return null;
      } else {
        return metaValue.getValue(prop.getChildren()); // 2.1.2 如果有值,取属性值
      }
    } else {
      return objectWrapper.get(prop); // 2.1.3获取ObjectWrapper中的属性值
    }
  }

使用POJO(Entity)的是BeanWrapper:

# mybatis-3.5.7.jar!/org.apache.ibatis.reflection.wrapper.BeanWrapper
  @Override
  public Object get(PropertyTokenizer prop) {
    if (prop.getIndex() != null) {
      Object collection = resolveCollection(prop, object); // 1. 根据属性名称获取对象
      return getCollectionValue(prop, collection); // 2. 根据索引位置获取对象
    } else {
      return getBeanProperty(prop, object);
    }
  }
  
  private Object getBeanProperty(PropertyTokenizer prop, Object object) {
    try {
      Invoker method = metaClass.getGetInvoker(prop.getName()); // 3. 获取对象类的getter方法(包装的方法)
      try {
        return method.invoke(object, NO_ARGUMENTS); // 反射调用getter方法(优先getter方法创建MethodInvoker,没有则使用字段创建GetFieldInvoker)
      } catch (Throwable t) {
        throw ExceptionUtil.unwrapThrowable(t);
      }
    } catch (RuntimeException e) {
      throw e;
    } catch (Throwable t) {
      throw new ReflectionException("Could not get property '" + prop.getName() + "' from " + object.getClass() + ".  Cause: " + t.toString(), t);
    }
  }  

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/22087.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们YX

mu99908888

在线咨询: 微信交谈

邮件:itzsgw@126.com

工作时间:时刻准备着!

关注微信