1. The simplest case: resultMap is not configured in xml, that is, the query is directly encapsulated into javabean.
mybatis source code:
DefaultResultSetHandler.class
//Query all columns written in sql from the wrapper class ResultSetWrapper of resultSet. final List<String> 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; } } //Query whether there is the property in the Object from the metaObject. metaObject is the wrapper class of ObjectWrapper.ObjectWrapper is the wrapper class of Object final String property = metaObject.findProperty(propertyName, configuration.isMapUnderscoreToCamelCase()); if (property != null && metaObject.hasSetter(property)) { //get the field type final Class<?> propertyType = metaObject.getSetterType(property); if (typeHandlerRegistry.hasTypeHandler(propertyType)) { //Get the typeHandler that handles the field type final TypeHandler<?> typeHandler = rsw.getTypeHandler(propertyType, columnName); //get value final Object value = typeHandler.getResult(rsw.getResultSet(), columnName); if (value != null || configuration.isCallSettersOnNulls()) { // issue #377, call setter on nulls if (value != null || !propertyType.isPrimitive()) { //Settings metaObject.setValue(property, value); } foundValues = true; } } } }
2. The principle of encapsulating one-to-many relationship or one-to-one relationship of collection:
First, when the project is loaded, read the <resultMap> tag in xml and encapsulate it into ResultMap, where each result in ResultMap corresponds to ResultMapping.
public class ResultMap { private String id; private Class<?> type; private List<ResultMapping> resultMappings; private List<ResultMapping> idResultMappings; private List<ResultMapping> constructorResultMappings; private List<ResultMapping> propertyResultMappings; private Set<String> mappedColumns; private Discriminator discriminator; private boolean hasNestedResultMaps; //Whether there are nested tags private boolean hasNestedQueries; private Boolean autoMapping; resultMap corresponds to the <resultMap> tag 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<String> notNullColumns; private String columnPrefix; private List<ResultFlag> flags; private List<ResultMapping> composites; private String resultSet; private String foreignColumn; private boolean lazy; ResultMapping corresponds to the <result tag><collection tag, etc.> under the <ResultMap> tag public class DefaultResultSetHandler implements ResultSetHandler This class is a class that handles result set mapping, which defines two Maps: private final Map<CacheKey, Object> nestedResultObjects = new HashMap<CacheKey, Object>(); When saving the entity class object in the one-to-many relationship mapping, first take the object from the Map, if there is one, take it out, if not, take it out New. CacheKey is generated based on the primary key. private final Map<CacheKey, Object> ancestorObjects = new HashMap<CacheKey, Object>(); Save the object of the entity nested class, first judge whether there is an object in the Map according to the CacheKey, if there is, take it out, if not, create a new one. CacheKey is generated based on the id of the nested class. This is why the id tag must be configured when configuring the collection, because when encapsulating a one-to-many relationship, it is based on the id to determine whether there is the same object and then encapsulate it.