Mybatis数据封装过程原理解析

阅读更多
mybatis封装数据过程:mybatis中大量使用了装饰设计模式。
1、最简单的一种情况:xml中没有配置resultMap也就是查询出来直接封装到javabean中。
mybatis源码:
DefaultResultSetHandler.class
//从resultSet的包装类ResultSetWrapper中查询出sql中写的所有column.
final List unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix);
    boolean foundValues = false;
    for (String columnName : unmappedColumnNames) {
      String propertyName = columnName;
      if (columnPrefix != null && columnPrefix.length() > 0) {
        // When columnPrefix is specified,
        // ignore columns without the prefix.
        if (columnName.toUpperCase(Locale.ENGLISH).startsWith(columnPrefix)) {
          propertyName = columnName.substring(columnPrefix.length());
        } else {
          continue;
        }
      }
      //从metaObject中查询出Object中是否有该property。metaObject是ObjectWrapper的包装类.ObjectWrapper是Object的包装类
      final String property = metaObject.findProperty(propertyName, configuration.isMapUnderscoreToCamelCase());
      if (property != null && metaObject.hasSetter(property)) {
	//拿到字段类型
        final Class propertyType = metaObject.getSetterType(property);
        if (typeHandlerRegistry.hasTypeHandler(propertyType)) {
	  //获取处理字段类型的typeHandler	
          final TypeHandler typeHandler = rsw.getTypeHandler(propertyType, columnName);
	  //获取值
          final Object value = typeHandler.getResult(rsw.getResultSet(), columnName);
          if (value != null || configuration.isCallSettersOnNulls()) { // issue #377, call setter on nulls
            if (value != null || !propertyType.isPrimitive()) {
	    //设置值
              metaObject.setValue(property, value);
            }
            foundValues = true;
          }
        }
      }
    }

2、封装collection一对多关系或者一对一关系的原理:
    首先项目加载的时候读取xml中的标签封装到ResultMap其中ResultMap中的每一个result对应ResultMapping.
public class ResultMap {
  private String id;
  private Class type;
  private List resultMappings;
  private List idResultMappings;
  private List constructorResultMappings;
  private List propertyResultMappings;
  private Set mappedColumns;
  private Discriminator discriminator;
  private boolean hasNestedResultMaps; //是否有嵌套标签
  private boolean hasNestedQueries;
  private Boolean autoMapping;
resultMap对应标签


public class ResultMapping {

  private Configuration configuration;
  private String property;
  private String column;
  private Class javaType;
  private JdbcType jdbcType;
  private TypeHandler typeHandler;
  private String nestedResultMapId;
  private String nestedQueryId;
  private Set notNullColumns;
  private String columnPrefix;
  private List flags;
  private List composites;
  private String resultSet;
  private String foreignColumn;
  private boolean lazy;
ResultMapping 对应标签下的

public class DefaultResultSetHandler implements ResultSetHandler这个类是处理结果集映射的类,其中定义了两个Map:
private final Map nestedResultObjects = new HashMap(); 保存实体类对象在一对多关系映射的时候,首先从该Map中取对象,如果有就取出来,如果没有就新建。CacheKey根据主键生成。

  private final Map ancestorObjects = new HashMap();保存实体嵌套类的对象,先从该Map中根据CacheKey判断是否有对象,有则取出,没有则新建。CacheKey根据嵌套类的id生成。这也是为什么当配置collection的时候一定要配置id标签,因为封装一对多关系的时候是根据id来判断是否存在同一对象进而封装。
 

你可能感兴趣的:(java)