编程语言
820
ResultMapping
对象是 mybatis 的 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); } } }