mybatis百科-列映射类ResultMapping

@

ResultMapping 对象是 mybatis 的 <resultMap> 节点在 ResultMap 对象中基础组成部分.

ResultMapping 对象记录了结果集中一列与队友JavaBean中一个属性的对应关系。

列映射

1 成员变量

// Configuration 对象, 看过前面源码的应该知道这个对象的含义
private Configuration configuration;
// 对应相应 JavaBean 中的成员变量
private String property;
// 对应节点的 column 属性, 对应检索出来的列名(别名)
private String column;
// 对应节点的 javaType 属性
private Class<?> javaType;
// 对应节点的 jdbcType 属性, 表示映射列的JDBC属性
private JdbcType jdbcType;
// 类型处理器
private TypeHandler<?> typeHandler;
// 对应另一个 resultMap 的 id, 负责将结果集中的一部分映射成其他对象。
private String nestedResultMapId;
// 
private String nestedQueryId;
// 对应节点的 notNullColumns 属性拆分后的结果
private Set<String> notNullColumns;
// 对应节点的 columnPrefix 属性
private String columnPrefix;
// 处理后的标记, 有两种:id和constructor
private List<ResultFlag> flags;
// 
private List<ResultMapping> composites;
// 对应节点的 resultSet 属性
private String resultSet;
// 对应节点的 foreignColumn 属性
private String foreignColumn;
// 是否延迟加载, 对应节点的 fetchType 属性
private boolean lazy;

2 构造函数

  ResultMapping() {
  }

就是一个空的构造函数

3 其他函数

3.1 setter 和 getter 函数

ResultMapping 对象创建使用的是建造者模式, 因此,只有部分成员变量含有 setter 函数。而除了 Configuration 对象, 其他都含有 getter 函数。

3.2 equals 和 hashCode 函数

该函数重写了 equals 方法。

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }

    ResultMapping that = (ResultMapping) o;

    if (property == null || !property.equals(that.property)) {
      return false;
    }

    return true;
  }

而 equals 重写, 则基本上 hashCode 也要重写。 以 property 或 column 的 hashCode 作为其 hashCode

  @Override
  public int hashCode() {
    if (property != null) {
      return property.hashCode();
    } else if (column != null) {
      return column.hashCode();
    } else {
      return 0;
    }
  }

3.3 toString 函数

  @Override
  public String toString() {
    final StringBuilder sb = new StringBuilder("ResultMapping{");
    //sb.append("configuration=").append(configuration); // configuration doesn't have a useful .toString()
    sb.append("property='").append(property).append('\'');
    sb.append(", column='").append(column).append('\'');
    sb.append(", javaType=").append(javaType);
    sb.append(", jdbcType=").append(jdbcType);
    //sb.append(", typeHandler=").append(typeHandler); // typeHandler also doesn't have a useful .toString()
    sb.append(", nestedResultMapId='").append(nestedResultMapId).append('\'');
    sb.append(", nestedQueryId='").append(nestedQueryId).append('\'');
    sb.append(", notNullColumns=").append(notNullColumns);
    sb.append(", columnPrefix='").append(columnPrefix).append('\'');
    sb.append(", flags=").append(flags);
    sb.append(", composites=").append(composites);
    sb.append(", resultSet='").append(resultSet).append('\'');
    sb.append(", foreignColumn='").append(foreignColumn).append('\'');
    sb.append(", lazy=").append(lazy);
    sb.append('}');
    return sb.toString();
  }

恨我们平常写的基本差不多。

4 内部类 Builder

ResultMapping 是使用建造者模式来进行创建的。

4.1 成员变量

private ResultMapping resultMapping = new ResultMapping();

4.2 构造函数

就是给部分属性赋值。

 public Builder(Configuration configuration, String property, String column, TypeHandler<?> typeHandler) {
      this(configuration, property);
      resultMapping.column = column;
      resultMapping.typeHandler = typeHandler;
    }

    public Builder(Configuration configuration, String property, String column, Class<?> javaType) {
      this(configuration, property);
      resultMapping.column = column;
      resultMapping.javaType = javaType;
    }

    public Builder(Configuration configuration, String property) {
      resultMapping.configuration = configuration;
      resultMapping.property = property;
      resultMapping.flags = new ArrayList<ResultFlag>();
      resultMapping.composites = new ArrayList<ResultMapping>();
      resultMapping.lazy = configuration.isLazyLoadingEnabled();
    }

4.3 建造者模式相关函数

除了 configuration, property, column, 其他成员变量都有类似如下的函数:
赋值后返回 Builder 对象本身。

public Builder javaType(Class<?> javaType) {
  resultMapping.javaType = javaType;
  return this;
}

建造对象的函数

public ResultMapping build() {
  // 返回不可更改的 List
  resultMapping.flags = Collections.unmodifiableList(resultMapping.flags);
  // 返回不可更改的 List
  resultMapping.composites = Collections.unmodifiableList(resultMapping.composites);
  resolveTypeHandler();
  // 校验
  validate();
  return resultMapping;
}

校验

// 对我们写的配置进行校验
private void validate() {
  // 不可同时定义 nestedQueryId 和 nestedResultMapId
  if (resultMapping.nestedQueryId != null && resultMapping.nestedResultMapId != null) {
    throw new IllegalStateException("Cannot define both nestedQueryId and nestedResultMapId in property " + resultMapping.property);
  }
  // nestedQueryId 、 nestedResultMapId 和 typeHandler 不能同时为 null
  if (resultMapping.nestedQueryId == null && resultMapping.nestedResultMapId == null && resultMapping.typeHandler == null) {
    throw new IllegalStateException("No typehandler found for property " + resultMapping.property);
  }
  // Issue #4 and GH #39: column is optional only in nested resultmaps but not in the rest
  if (resultMapping.nestedResultMapId == null && resultMapping.column == null && resultMapping.composites.isEmpty()) {
    throw new IllegalStateException("Mapping is missing column attribute for property " + resultMapping.property);
  }
  if (resultMapping.getResultSet() != null) {
    int numColumns = 0;
    if (resultMapping.column != null) {
      numColumns = resultMapping.column.split(",").length;
    }
    int numForeignColumns = 0;
    if (resultMapping.foreignColumn != null) {
      numForeignColumns = resultMapping.foreignColumn.split(",").length;
    }
    if (numColumns != numForeignColumns) {
      throw new IllegalStateException("There should be the same number of columns and foreignColumns in property " + resultMapping.property);
    }
  }
}
    

一起学 mybatis

你想不想来学习 mybatis? 学习其使用和源码呢?那么, 在博客园关注我吧!!

我自己打算把这个源码系列更新完毕, 同时会更新相应的注释。快去 star 吧!!

mybatis最新源码和注释

github项目

posted @ 2018-10-22 23:27 阿进的写字台 阅读(...) 评论(...) 编辑 收藏