mybatis百科-結果集對映類ResultMap
阿新 • • 發佈:2018-12-17
ResultMap
對應的是結果集 <resultMap>中的一個結果集。 其基本組成部分中, 含有 ResultMapping
物件。
其組成大致如下:
本文, 主要講解一下該類的組成。
1 成員變數
// resultMap 節點的 id private String id; // resultMap 節點的 type private Class<?> type; // 用於記錄 <discriminayor> 節點之外的其他對映關係 private List<ResultMapping> resultMappings; // 記錄對映關係中帶有 ID 標記的對映關係。 如 id, constructor 等節點 private List<ResultMapping> idResultMappings; // 記錄對映關係中有 Constructor 標記的對映關係 private List<ResultMapping> constructorResultMappings; // 記錄對映關係中沒有 Constructor 標記的對映關係 private List<ResultMapping> propertyResultMappings; // 記錄所有對映關係中涉及 column 屬性的集合 private Set<String> mappedColumns; private Set<String> mappedProperties; // 鑑別器, 對應 <discriminayor> 節點 private Discriminator discriminator; // 是否含有巢狀的結果對映, 如果某個對映關係中有 resultMap, 沒有 resultSet , 則為true private boolean hasNestedResultMaps; // 是否存在巢狀查詢 private boolean hasNestedQueries; // 是否開啟自動對映 private Boolean autoMapping;
2 建構函式
只有預設建構函式
private ResultMap() {
}
3 其他函式
3.1 setter 和 getter 函式
物件建立使用的是建造者模式, 因此,只有部分成員變數含有 setter 函式。而除了 Configuration 物件, 其他都含有 getter 函式。
4 靜態內部類
4.1 成員變數
private ResultMap resultMap = new ResultMap();
是要建造的物件。
4.2 建構函式
public Builder(Configuration configuration, String id, Class<?> type, List<ResultMapping> resultMappings) { this(configuration, id, type, resultMappings, null); } public Builder(Configuration configuration, String id, Class<?> type, List<ResultMapping> resultMappings, Boolean autoMapping) { resultMap.configuration = configuration; resultMap.id = id; resultMap.type = type; resultMap.resultMappings = resultMappings; resultMap.autoMapping = autoMapping; }
沒有預設建構函式, 必須要給ResultMap
物件的一些成員變數賦值。
4.3 建造者相關的函式
public Builder discriminator(Discriminator discriminator) {
resultMap.discriminator = discriminator;
return this;
}
discriminator, 賦值後返回物件本身。
負責建造物件一些邏輯的函式。
public ResultMap build() { if (resultMap.id == null) { throw new IllegalArgumentException("ResultMaps must have an id"); } resultMap.mappedColumns = new HashSet<>(); resultMap.mappedProperties = new HashSet<>(); resultMap.idResultMappings = new ArrayList<>(); resultMap.constructorResultMappings = new ArrayList<>(); resultMap.propertyResultMappings = new ArrayList<>(); final List<String> constructorArgNames = new ArrayList<>(); // 遍歷 resultMappings for (ResultMapping resultMapping : resultMap.resultMappings) { // 是否存在巢狀查詢 resultMap.hasNestedQueries = resultMap.hasNestedQueries || resultMapping.getNestedQueryId() != null; // 是否存在巢狀的結果 resultMap.hasNestedResultMaps = resultMap.hasNestedResultMaps || (resultMapping.getNestedResultMapId() != null && resultMapping.getResultSet() == null); // 獲取列名 final String column = resultMapping.getColumn(); if (column != null) { // 列名轉大寫新增到 mappedColumns 結果集中 resultMap.mappedColumns.add(column.toUpperCase(Locale.ENGLISH)); } else if (resultMapping.isCompositeResult()) { for (ResultMapping compositeResultMapping : resultMapping.getComposites()) { final String compositeColumn = compositeResultMapping.getColumn(); if (compositeColumn != null) { resultMap.mappedColumns.add(compositeColumn.toUpperCase(Locale.ENGLISH)); } } } // 獲取列對映對應的屬性 final String property = resultMapping.getProperty(); if(property != null) { resultMap.mappedProperties.add(property); } if (resultMapping.getFlags().contains(ResultFlag.CONSTRUCTOR)) { resultMap.constructorResultMappings.add(resultMapping); if (resultMapping.getProperty() != null) { constructorArgNames.add(resultMapping.getProperty()); } } else { resultMap.propertyResultMappings.add(resultMapping); } if (resultMapping.getFlags().contains(ResultFlag.ID)) { resultMap.idResultMappings.add(resultMapping); } } if (resultMap.idResultMappings.isEmpty()) { resultMap.idResultMappings.addAll(resultMap.resultMappings); } if (!constructorArgNames.isEmpty()) { final List<String> actualArgNames = argNamesOfMatchingConstructor(constructorArgNames); if (actualArgNames == null) { throw new BuilderException("Error in result map '" + resultMap.id + "'. Failed to find a constructor in '" + resultMap.getType().getName() + "' by arg names " + constructorArgNames + ". There might be more info in debug log."); } Collections.sort(resultMap.constructorResultMappings, (o1, o2) -> { int paramIdx1 = actualArgNames.indexOf(o1.getProperty()); int paramIdx2 = actualArgNames.indexOf(o2.getProperty()); return paramIdx1 - paramIdx2; }); } // lock down collections resultMap.resultMappings = Collections.unmodifiableList(resultMap.resultMappings); resultMap.idResultMappings = Collections.unmodifiableList(resultMap.idResultMappings); resultMap.constructorResultMappings = Collections.unmodifiableList(resultMap.constructorResultMappings); resultMap.propertyResultMappings = Collections.unmodifiableList(resultMap.propertyResultMappings); resultMap.mappedColumns = Collections.unmodifiableSet(resultMap.mappedColumns); return resultMap; }
4.4 獲取配置的構造方法引數列表
主函式是argNamesOfMatchingConstructor
。 其功能主要是獲取引數名。
private List<String> argNamesOfMatchingConstructor(List<String> constructorArgNames) {
// 獲取宣告的構造方法
Constructor<?>[] constructors = resultMap.type.getDeclaredConstructors();
// 遍歷每個構造方法
for (Constructor<?> constructor : constructors) {
// 獲取構造方法的引數型別
Class<?>[] paramTypes = constructor.getParameterTypes();
// 引數長度和獲取到引數型別數量一致
if (constructorArgNames.size() == paramTypes.length) {
// 獲取建構函式的引數名稱
List<String> paramNames = getArgNames(constructor);
if (constructorArgNames.containsAll(paramNames)
&& argTypesMatch(constructorArgNames, paramTypes, paramNames)) {
return paramNames;
}
}
}
return null;
}
getArgNames
獲取建構函式的引數名
private List<String> getArgNames(Constructor<?> constructor) {
List<String> paramNames = new ArrayList<>();
List<String> actualParamNames = null;
// 獲取引數的註解
final Annotation[][] paramAnnotations = constructor.getParameterAnnotations();
int paramCount = paramAnnotations.length;
for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) {
String name = null;
for (Annotation annotation : paramAnnotations[paramIndex]) {
if (annotation instanceof Param) {
name = ((Param) annotation).value();
break;
}
}
if (name == null && resultMap.configuration.isUseActualParamName()) {
if (actualParamNames == null) {
actualParamNames = ParamNameUtil.getParamNames(constructor);
}
if (actualParamNames.size() > paramIndex) {
name = actualParamNames.get(paramIndex);
}
}
paramNames.add(name != null ? name : "arg" + paramIndex);
}
return paramNames;
}
}
argTypesMatch
方法用來檢查構造方法引數是否匹配
private boolean argTypesMatch(final List<String> constructorArgNames,
Class<?>[] paramTypes, List<String> paramNames) {
for (int i = 0; i < constructorArgNames.size(); i++) {
Class<?> actualType = paramTypes[paramNames.indexOf(constructorArgNames.get(i))];
Class<?> specifiedType = resultMap.constructorResultMappings.get(i).getJavaType();
if (!actualType.equals(specifiedType)) {
if (log.isDebugEnabled()) {
log.debug("While building result map '" + resultMap.id
+ "', found a constructor with arg names " + constructorArgNames
+ ", but the type of '" + constructorArgNames.get(i)
+ "' did not match. Specified: [" + specifiedType.getName() + "] Declared: ["
+ actualType.getName() + "]");
}
return false;
}
}
return true;
}