您的位置:首页 > 移动开发

Mybatis工作机制源码分析—初始化—mapper配置文件解析

2017-01-05 13:46 1186 查看
      本文以源码分析的形式讲解Mybatis是如何进行mapper配置文件的解析工作的。

时序图



相关源码

/** XMLMapperBuilder.java */
// 构造XMLMapperBuilder
public XMLMapperBuilder(InputStream inputStream, Configuration configuration, String resource, Map<String, XNode> sqlFragments) {
this(new XPathParser(inputStream, true, configuration.getVariables(), new XMLMapperEntityResolver()),
configuration, resource, sqlFragments);
}

private XMLMapperBuilder(XPathParser parser, Configuration configuration, String resource, Map<String, XNode> sqlFragments) {
super(configuration);
this.builderAssistant = new MapperBuilderAssistant(configuration, resource);
this.parser = parser;
this.sqlFragments = sqlFragments;
this.resource = resource;
}

// MyBatis mapper配置文件解析
public void parse() {
if (!configuration.isResourceLoaded(resource)) {
// parser.evalNode("/mapper"):获取Mybatis mapper配置文件的根节点XNode
configurationElement(parser.evalNode("/mapper"));
// resource添加到loadedResources
configuration.addLoadedResource(resource);
bindMapperForNamespace();
}

parsePendingResultMaps();
parsePendingChacheRefs();
parsePendingStatements();
}

private void configurationElement(XNode context) {
try {
// 获取<mapper>的"namespace"属性
String namespace = context.getStringAttribute("namespace");
if (namespace == null || namespace.equals("")) {
throw new BuilderException("Mapper's namespace cannot be empty");
}
// builderAssistant设置currentNamespace
builderAssistant.setCurrentNamespace(namespace);
// 解析"mapper\cache-ref"元素
cacheRefElement(context.evalNode("cache-ref"));
// 解析"mapper\cache"元素
cacheElement(context.evalNode("cache"));
// 解析"/mapper/parameterMap"元素
parameterMapElement(context.evalNodes("/mapper/parameterMap"));
// 解析"/mapper/resultMap"元素
resultMapElements(context.evalNodes("/mapper/resultMap"));
// 解析"/mapper/sql"元素
sqlElement(context.evalNodes("/mapper/sql"));
// 解析"/mapper/select|insert|update|delete"元素
buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
} catch (Exception e) {
throw new BuilderException("Error parsing Mapper XML. Cause: " + e, e);
}
}

详细流程

解析"mapper\cache-ref"元素
private void cacheRefElement(XNode context) {
if (context != null) {
// configuration cacheRefMap添加缓存引用键值对
configuration.addCacheRef(builderAssistant.getCurrentNamespace(), context.getStringAttribute("namespace"));
CacheRefResolver cacheRefResolver = new CacheRefResolver(builderAssistant, context.getStringAttribute("namespace"));
try {
// 设置MapperBuilderAssistant的currentCache为"namespace"引用的缓存
cacheRefResolver.resolveCacheRef();
} catch (IncompleteElementException e) {
configuration.addIncompleteCacheRef(cacheRefResolver);
}
}
}

/** Configuration.java */
public void addCacheRef(String namespace, String referencedNamespace) {
cacheRefMap.put(namespace, referencedNamespace);
}

/** CacheRefResolver.java */
public CacheRefResolver(MapperBuilderAssistant assistant, String cacheRefNamespace) {
this.assistant = assistant;
this.cacheRefNamespace = cacheRefNamespace;
}

public Cache resolveCacheRef() {
return assistant.useCacheRef(cacheRefNamespace);
}

/** MapperBuilderAssistant.java */
// 设置MapperBuilderAssistant的currentCache为namespace对应的缓存
public Cache useCacheRef(String namespace) {
if (namespace == null) {
throw new BuilderException("cache-ref element requires a namespace attribute.");
}
try {
unresolvedCacheRef = true;
Cache cache = configuration.getCache(namespace);
if (cache == null) {
throw new IncompleteElementException("No cache for namespace '" + namespace + "' could be found.");
}
currentCache = cache;
unresolvedCacheRef = false;
return cache;
} catch (IllegalArgumentException e) {
throw new IncompleteElementException("No cache for namespace '" + namespace + "' could be found.", e);
}
}
解析"mapper\cache"元素
/** XMLMapperBuilder.java */
private void cacheElement(XNode context) throws Exception {
if (context != null) {
// 获取<cache>的"type"属性,默认为PerpetualCache
String type = context.getStringAttribute("type", "PERPETUAL");
Class<? extends Cache> typeClass = typeAliasRegistry.resolveAlias(type);
// 获取<cache>的"eviction"属性,默认为LruCache
String eviction = context.getStringAttribute("eviction", "LRU");
Class<? extends Cache> evictionClass = typeAliasRegistry.resolveAlias(eviction);
// 获取<cache>的"flushInterval"属性,缓存刷新间隔时间
Long flushInterval = context.getLongAttribute("flushInterval");
// 获取<cache>的"size"属性,缓存引用的最大数
Integer size = context.getIntAttribute("size");
// 获取<cache>的"readOnly"属性,默认为false
boolean readWrite = !context.getBooleanAttribute("readOnly", false);
// 获取<cache>的"blocking"属性,默认为false
boolean blocking = context.getBooleanAttribute("blocking", false);
Properties props = context.getChildrenAsProperties();
builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, blocking, props);
}
}

/** MapperBuilderAssistant.java */
public Cache useNewCache(Class<? extends Cache> typeClass,
Class<? extends Cache> evictionClass,
Long flushInterval,
Integer size,
boolean readWrite,
boolean blocking,
Properties props) {
typeClass = valueOrDefault(typeClass, PerpetualCache.class);
evictionClass = valueOrDefault(evictionClass, LruCache.class);
// 根据相关属性,构建cache
Cache cache = new CacheBuilder(currentNamespace)
.implementation(typeClass)
.addDecorator(evictionClass)
.clearInterval(flushInterval)
.size(size)
.readWrite(readWrite)
.blocking(blocking)
.properties(props)
.build();
// 添加到configuration caches
configuration.addCache(cache);
// 设置为builderAssistant的currentCache
currentCache = cache;
return cache;
}

/** CacheBuilder.java */
public Cache build() {
// 设置CacheBuilder中implementation、decorators相关默认值
setDefaultImplementations();
// 创建implementation Cache
Cache cache = newBaseCacheInstance(implementation, id);
// 用properties设置cache相关属性
setCacheProperties(cache);
// issue #352, do not apply decorators to custom caches
if (PerpetualCache.class.equals(cache.getClass())) {
for (Class<? extends Cache> decorator : decorators) {
// 用Constructor反射装饰Cache
cache = newCacheDecoratorInstance(decorator, cache);
// 重新用properties设置cache相关属性
setCacheProperties(cache);
}
cache = setStandardDecorators(cache);
} else if (!LoggingCache.class.isAssignableFrom(cache.getClass())) {
cache = new LoggingCache(cache);
}
return cache;
}

private void setDefaultImplementations() {
if (implementation == null) {
implementation = PerpetualCache.class;
if (decorators.isEmpty()) {
decorators.add(LruCache.class);
}
}
}

// 用Constructor反射构建Cache
private Cache newBaseCacheInstance(Class<? extends Cache> cacheClass, String id) {
Constructor<? extends Cache> cacheConstructor = getBaseCacheConstructor(cacheClass);
try {
return cacheConstructor.newInstance(id);
} catch (Exception e) {
throw new CacheException("C
4000
ould not instantiate cache implementation (" + cacheClass + "). Cause: " + e, e);
}
}

// 用反射设置cache相关参数
private void setCacheProperties(Cache cache) {
if (properties != null) {
MetaObject metaCache = SystemMetaObject.forObject(cache);
for (Map.Entry<Object, Object> entry : properties.entrySet()) {
String name = (String) entry.getKey();
String value = (String) entry.getValue();
if (metaCache.hasSetter(name)) {
Class<?> type = metaCache.getSetterType(name);
if (String.class == type) {
metaCache.setValue(name, value);
} else if (int.class == type
|| Integer.class == type) {
metaCache.setValue(name, Integer.valueOf(value));
} else if (long.class == type
|| Long.class == type) {
metaCache.setValue(name, Long.valueOf(value));
} else if (short.class == type
|| Short.class == type) {
metaCache.setValue(name, Short.valueOf(value));
} else if (byte.class == type
|| Byte.class == type) {
metaCache.setValue(name, Byte.valueOf(value));
} else if (float.class == type
|| Float.class == type) {
metaCache.setValue(name, Float.valueOf(value));
} else if (boolean.class == type
|| Boolean.class == type) {
metaCache.setValue(name, Boolean.valueOf(value));
} else if (double.class == type
|| Double.class == type) {
metaCache.setValue(name, Double.valueOf(value));
} else {
throw new CacheException("Unsupported property type for cache: '" + name + "' of type " + type);
}
}
}
}
}

// 用Constructor反射装饰Cache
private Cache newCacheDecoratorInstance(Class<? extends Cache> cacheClass, Cache base) {
Constructor<? extends Cache> cacheConstructor = getCacheDecoratorConstructor(cacheClass);
try {
return cacheConstructor.newInstance(base);
} catch (Exception e) {
throw new CacheException("Could not instantiate cache decorator (" + cacheClass + "). Cause: " + e, e);
}
}

// 用Standard Decorator装饰cache
private Cache setStandardDecorators(Cache cache) {
try {
// 设置size属性
MetaObject metaCache = SystemMetaObject.forObject(cache);
if (size != null && metaCache.hasSetter("size")) {
metaCache.setValue("size", size);
}
// ScheduledCache装饰cache,设置clearInterval,即缓存clear时间间隔
if (clearInterval != null) {
cache = new ScheduledCache(cache);
((ScheduledCache) cache).setClearInterval(clearInterval);
}
// SerializedCache装饰cache,表明cache可序列化读写
if (readWrite) {
cache = new SerializedCache(cache);
}
// LoggingCache装饰cache,记录缓存命中率(即getObject成功)的日志
cache = new LoggingCache(cache);
// SynchronizedCache装饰cache,缓存相关操作线程安全,通过在相关方法上加synchronized实现
cache = new SynchronizedCache(cache);
if (blocking) {
// BlockingCache装饰cache,缓存相关操作(getObject、putObject)通过获取对应key的lock进行
cache = new BlockingCache(cache);
}
return cache;
} catch (Exception e) {
throw new CacheException("Error building standard cache decorators. Cause: " + e, e);
}
}
解析"/mapper/parameterMap"元素
/** XMLMapperBuilder.java */
// 解析"/mapper/parameterMap"元素
private void parameterMapElement(List<XNode> list) throws Exception {
for (XNode parameterMapNode : list) {
// 获取id属性
String id = parameterMapNode.getStringAttribute("id");
// 获取type属性
String type = parameterMapNode.getStringAttribute("type");
// type属性对应的parameterClass
Class<?> parameterClass = resolveClass(type);
// 解析"/mapper/parameterMap/parameter"元素列表
List<XNode> parameterNodes = parameterMapNode.evalNodes("parameter");
List<ParameterMapping> parameterMappings = new ArrayList<ParameterMapping>();
for (XNode parameterNode : parameterNodes) {
// 获取<parameter>的property属性
String property = parameterNode.getStringAttribute("property");
// 获取<parameter>的javaType属性
String javaType = parameterNode.getStringAttribute("javaType");
// 获取<parameter>的jdbcType属性
String jdbcType = parameterNode.getStringAttribute("jdbcType");
// 获取<parameter>的resultMap属性
String resultMap = parameterNode.getStringAttribute("resultMap");
// 获取<parameter>的mode属性
String mode = parameterNode.getStringAttribute("mode");
// 获取<parameter>的typeHandler属性
String typeHandler = parameterNode.getStringAttribute("typeHandler");
// 获取<parameter>的numericScale属性
Integer numericScale = parameterNode.getIntAttribute("numericScale");
// 解析参数的模式(ParameterMode.IN, ParameterMode.OUT, ParameterMode.INOUT)
ParameterMode modeEnum = resolveParameterMode(mode);
// 解析javaType对应的Class
Class<?> javaTypeClass = resolveClass(javaType);
// 解析jdbcType对应的JdbcType类型
JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
// 解析typeHandler对应的Class类型
@SuppressWarnings("unchecked")
Class<? extends TypeHandler<?>> typeHandlerClass = (Class<? extends TypeHandler<?>>) resolveClass(typeHandler);
// 构建ParameterMapping
ParameterMapping parameterMapping = builderAssistant.buildParameterMapping(parameterClass, property, javaTypeClass, jdbcTypeEnum, resultMap, modeEnum, typeHandlerClass, numericScale);
parameterMappings.add(parameterMapping);
}
// configuration添加parameterMap
builderAssistant.addParameterMap(id, parameterClass, parameterMappings);
}
}

/** BaseBuilder.java */
protected ParameterMode resolveParameterMode(String alias) {
if (alias == null) {
return null;
}
try {
return ParameterMode.valueOf(alias);
} catch (IllegalArgumentException e) {
throw new BuilderException("Error resolving ParameterMode. Cause: " + e, e);
}
}

protected JdbcType resolveJdbcType(String alias) {
if (alias == null) {
return null;
}
try {
return JdbcType.valueOf(alias);
} catch (IllegalArgumentException e) {
throw new BuilderException("Error resolving JdbcType. Cause: " + e, e);
}
}

protected Class<?> resolveClass(String alias) {
if (alias == null) {
return null;
}
try {
return resolveAlias(alias);
} catch (Exception e) {
throw new BuilderException("Error resolving class. Cause: " + e, e);
}
}

/** MapperBuilderAssistant.java */
// 构建ParameterMapping
public ParameterMapping buildParameterMapping(
Class<?> parameterType,
String property,
Class<?> javaType,
JdbcType jdbcType,
String resultMap,
ParameterMode parameterMode,
Class<? extends TypeHandler<?>> typeHandler,
Integer numericScale) {
// 带上currentNamespace前缀
resultMap = applyCurrentNamespace(resultMap, true);

// Class parameterType = parameterMapBuilder.type();
// 确定javaTypeClass
Class<?> javaTypeClass = resolveParameterJavaType(parameterType, property, javaType, jdbcType);
// 获取TypeHandler实例
TypeHandler<?> typeHandlerInstance = resolveTypeHandler(javaTypeClass, typeHandler);

// 构建ParameterMapping
ParameterMapping.Builder builder = new ParameterMapping.Builder(configuration, property, javaTypeClass);
builder.jdbcType(jdbcType);
builder.resultMapId(resultMap);
builder.mode(parameterMode);
builder.numericScale(numericScale);
builder.typeHandler(typeHandlerInstance);
return builder.build();
}

// 根据resultType、property、javaType、jdbcType确定javaType对应的Class
private Class<?> resolveParameterJavaType(Class<?> resultType, String property, Class<?> javaType, JdbcType jdbcType) {
if (javaType == null) { // javaType为null
if (JdbcType.CURSOR.equals(jdbcType)) {
// jdbcType为JdbcType.CURSOR,则javaType为java.sql.ResultSet.class
javaType = java.sql.ResultSet.class;
} else if (Map.class.isAssignableFrom(resultType)) {
// resultType为Map系列,javaType为Object.class
javaType = Object.class;
} else {
// 用resultType、property反射获取javaType对应的Class
MetaClass metaResultType = MetaClass.forClass(resultType, configuration.getReflectorFactory());
javaType = metaResultType.getGetterType(property);
}
}
if (javaType == null) {
javaType = Object.class;
}
return javaType;
}

/** BaseBuilder.java */
// 根据javaType、typeHandlerType获取TypeHandler实例
protected TypeHandler<?> resolveTypeHandler(Class<?> javaType, Class<? extends TypeHandler<?>> typeHandlerType) {
if (typeHandlerType == null) {
return null;
}
// javaType ignored for injected handlers see issue #746 for full detail
TypeHandler<?> handler = typeHandlerRegistry.getMappingTypeHandler(typeHandlerType);
if (handler == null) {
// not in registry, create a new one
handler = typeHandlerRegistry.getInstance(javaType, typeHandlerType);
}
return handler;
}

/** MapperBuilderAssistant.java */
public ParameterMap addParameterMap(String id, Class<?> parameterClass, List<ParameterMapping> parameterMappings) {
// 带上currentNamespace前缀
id = applyCurrentNamespace(id, false);
// 构建ParameterMap
ParameterMap.Builder parameterMapBuilder = new ParameterMap.Builder(configuration, id, parameterClass, parameterMappings);
ParameterMap parameterMap = parameterMapBuilder.build();
// configuration添加parameterMap
configuration.addParameterMap(parameterMap);
return parameterMap;
}
解析"/mapper/resultMap"元素
/** XMLMapperBuilder.java */
// 解析"/mapper/resultMap"元素
private void resultMapElements(List<XNode> list) throws Exception {
for (XNode resultMapNode : list) {
try {
resultMapElement(resultMapNode);
} catch (IncompleteElementException e) {
// ignore, it will be retried
}
}
}

private ResultMap resultMapElement(XNode resultMapNode) throws Exception {
return resultMapElement(resultMapNode, Collections.<ResultMapping> emptyList());
}

private ResultMap resultMapElement(XNode resultMapNode, List<ResultMapping> additionalResultMappings) throws Exception {
ErrorContext.instance().activity("processing " + resultMapNode.getValueBasedIdentifier());
// 获取<resultMap>的"id"属性
String id = resultMapNode.getStringAttribute("id",
resultMapNode.getValueBasedIdentifier());
// 获取<resultMap>的"type"属性
String type = resultMapNode.getStringAttribute("type",
resultMapNode.getStringAttribute("ofType",
resultMapNode.getStringAttribute("resultType",
resultMapNode.getStringAttribute("javaType"))));
// 获取<resultMap>的"extends"属性
String extend = resultMapNode.getStringAttribute("extends");
// 获取<resultMap>的"autoMapping"属性
Boolean autoMapping = resultMapNode.getBooleanAttribute("autoMapping");
Class<?> typeClass = resolveClass(type);
Discriminator discriminator = null;
List<ResultMapping> resultMappings = new ArrayList<ResultMapping>();
resultMappings.addAll(additionalResultMappings);
List<XNode> resultChildren = resultMapNode.getChildren();
for (XNode resultChild : resultChildren) {
if ("constructor".equals(resultChild.getName())) {
// 处理"/mapper/resultMap/constructor"元素
processConstructorElement(resultChild, typeClass, resultMappings);
} else if ("discriminator".equals(resultChild.getName())) {
// 处理"/mapper/resultMap/discriminator"元素
discriminator = processDiscriminatorElement(resultChild, typeClass, resultMappings);
} else {
// 处理"/mapper/resultMap/id"元素
List<ResultFlag> flags = new ArrayList<ResultFlag>();
if ("id".equals(resultChild.getName())) {
flags.add(ResultFlag.ID);
}
resultMappings.add(buildResultMappingFromContext(resultChild, typeClass, flags));
}
}
ResultMapResolver resultMapResolver = new ResultMapResolver(builderAssistant, id, typeClass, extend, discriminator, resultMappings, autoMapping);
try {
// 解析为ResultMap
return resultMapResolver.resolve();
} catch (IncompleteElementException e) {
configuration.addIncompleteResultMap(resultMapResolver);
throw e;
}
}

private void processConstructorElement(XNode resultChild, Class<?> resultType, List<ResultMapping> resultMappings) throws Exception {
List<XNode> argChildren = resultChild.getChildren();
for (XNode argChild : argChildren) {
List<ResultFlag> flags = new ArrayList<ResultFlag>();
flags.add(ResultFlag.CONSTRUCTOR);
if ("idArg".equals(argChild.getName())) {
flags.add(ResultFlag.ID);
}
resultMappings.add(buildResultMappingFromContext(argChild, resultType, flags));
}
}

private ResultMapping buildResultMappingFromContext(XNode context, Class<?> resultType, List<ResultFlag> flags) throws Exception {
// 获取相关属性
String property = context.getStringAttribute("property");
String column = context.getStringAttribute("column");
String javaType = context.getStringAttribute("javaType");
String jdbcType = context.getStringAttribute("jdbcType");
String nestedSelect = context.getStringAttribute("select");
String nestedResultMap = context.getStringAttribute("resultMap",
processNestedResultMappings(context, Collections.<ResultMapping> emptyList()));
String notNullColumn = context.getStringAttribute("notNullColumn");
String columnPrefix = context.getStringAttribute("columnPrefix");
String typeHandler = context.getStringAttribute("typeHandler");
String resulSet = context.getStringAttribute("resultSet");
String foreignColumn = context.getStringAttribute("foreignColumn");
boolean lazy = "lazy".equals(context.getStringAttribute("fetchType", configuration.isLazyLoadingEnabled() ? "lazy" : "eager"));
Class<?> javaTypeClass = resolveClass(javaType);
@SuppressWarnings("unchecked")
Class<? extends TypeHandler<?>> typeHandlerClass = (Class<? extends TypeHandler<?>>) resolveClass(typeHandler);
JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
return builderAssistant.buildResultMapping(resultType, property, column, javaTypeClass, jdbcTypeEnum, nestedSelect, nestedResultMap, notNullColumn, columnPrefix, typeHandlerClass, flags, resulSet, foreignColumn, lazy);
}

/** MapperBuilderAssistant.java */
// 构建ResultMapping
public ResultMapping buildResultMapping(
Class<?> resultType,
String property,
String column,
Class<?> javaType,
JdbcType jdbcType,
String nestedSelect,
String nestedResultMap,
String notNullColumn,
String columnPrefix,
Class<? extends TypeHandler<?>> typeHandler,
List<ResultFlag> flags,
String resultSet,
String foreignColumn,
boolean lazy) {
Class<?> javaTypeClass = resolveResultJavaType(resultType, property, javaType);
TypeHandler<?> typeHandlerInstance = resolveTypeHandler(javaTypeClass, typeHandler);
List<ResultMapping> composites = parseCompositeColumnName(column);
if (composites.size() > 0) {
column = null;
}
ResultMapping.Builder builder = new ResultMapping.Builder(configuration, property, column, javaTypeClass);
builder.jdbcType(jdbcType);
builder.nestedQueryId(applyCurrentNamespace(nestedSelect, true));
builder.nestedResultMapId(applyCurrentNamespace(nestedResultMap, true));
builder.resultSet(resultSet);
builder.typeHandler(typeHandlerInstance);
builder.flags(flags == null ? new ArrayList<ResultFlag>() : flags);
builder.composites(composites);
builder.notNullColumns(parseMultipleColumnNames(notNullColumn));
builder.columnPrefix(columnPrefix);
builder.foreignColumn(foreignColumn);
builder.lazy(lazy);
return builder.build();
}

/** XMLMapperBuilder.java */
private Discriminator processDiscriminatorElement(XNode context, Class<?> resultType, List<ResultMapping> resultMappings) throws Exception {
String column = context.getStringAttribute("column");
String javaType = context.getStringAttribute("javaType");
String jdbcType = context.getStringAttribute("jdbcType");
String typeHandler = context.getStringAttribute("typeHandler");
Class<?> javaTypeClass = resolveClass(javaType);
@SuppressWarnings("unchecked")
Class<? extends TypeHandler<?>> typeHandlerClass = (Class<? extends TypeHandler<?>>) reso
e844
lveClass(typeHandler);
JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
Map<String, String> discriminatorMap = new HashMap<String, String>();
// 获取discriminatorMap
for (XNode caseChild : context.getChildren()) {
String value = caseChild.getStringAttribute("value");
String resultMap = caseChild.getStringAttribute("resultMap", processNestedResultMappings(caseChild, resultMappings));
discriminatorMap.put(value, resultMap);
}
// 构建Discriminator
return builderAssistant.buildDiscriminator(resultType, column, javaTypeClass, jdbcTypeEnum, typeHandlerClass, discriminatorMap);
}

/** MapperBuilderAssistant.java */
public Discriminator buildDiscriminator(
Class<?> resultType,
String column,
Class<?> javaType,
JdbcType jdbcType,
Class<? extends TypeHandler<?>> typeHandler,
Map<String, String> discriminatorMap) {
// 构建resultMapping
ResultMapping resultMapping = buildResultMapping(
resultType,
null,
column,
javaType,
jdbcType,
null,
null,
null,
null,
typeHandler,
new ArrayList<ResultFlag>(),
null,
null,
false);
// discriminatorMap带上namespace
Map<String, String> namespaceDiscriminatorMap = new HashMap<String, String>();
for (Map.Entry<String, String> e : discriminatorMap.entrySet()) {
String resultMap = e.getValue();
resultMap = applyCurrentNamespace(resultMap, true);
namespaceDiscriminatorMap.put(e.getKey(), resultMap);
}
// 构建Discriminator
Discriminator.Builder discriminatorBuilder = new Discriminator.Builder(configuration, resultMapping, namespaceDiscriminatorMap);
return discriminatorBuilder.build();
}

/** ResultMapResolver.java */
// 解析ResultMap
public ResultMap resolve() {
return assistant.addResultMap(this.id, this.type, this.extend, this.discriminator, this.resultMappings, this.autoMapping);
}

/** MapperBuilderAssistant.java */
public ResultMap addResultMap(
String id,
Class<?> type,
String extend,
Discriminator discriminator,
List<ResultMapping> resultMappings,
Boolean autoMapping) {
id = applyCurrentNamespace(id, false);
extend = applyCurrentNamespace(extend, true);

ResultMap.Builder resultMapBuilder = new ResultMap.Builder(configuration, id, type, resultMappings, autoMapping);
if (extend != null) {
// 整合extend ResultMap
if (!configuration.hasResultMap(extend)) {
throw new IncompleteElementException("Could not find a parent resultmap with id '" + extend + "'");
}
ResultMap resultMap = configuration.getResultMap(extend);
List<ResultMapping> extendedResultMappings = new ArrayList<ResultMapping>(resultMap.getResultMappings());
// 删除重复的ResultMapping
extendedResultMappings.removeAll(resultMappings);
// Remove parent constructor if this resultMap declares a constructor.
boolean declaresConstructor = false;
for (ResultMapping resultMapping : resultMappings) {
if (resultMapping.getFlags().contains(ResultFlag.CONSTRUCTOR)) {
declaresConstructor = true;
break;
}
}
if (declaresConstructor) {
Iterator<ResultMapping> extendedResultMappingsIter = extendedResultMappings.iterator();
while (extendedResultMappingsIter.hasNext()) {
if (extendedResultMappingsIter.next().getFlags().contains(ResultFlag.CONSTRUCTOR)) {
extendedResultMappingsIter.remove();
}
}
}
resultMappings.addAll(extendedResultMappings);
}
resultMapBuilder.discriminator(discriminator);
// 构建ResultMap
ResultMap resultMap = resultMapBuilder.build();
// 添加到configuration
configuration.addResultMap(resultMap);
return resultMap;
}
解析"/mapper/sql"元素
/** XMLMapperBuilder.java */
private void sqlElement(List<XNode> list) throws Exception {
if (configuration.getDatabaseId() != null) {
sqlElement(list, configuration.getDatabaseId());
}
sqlElement(list, null);
}

private void sqlElement(List<XNode> list, String requiredDatabaseId) throws Exception {
for (XNode context : list) {
String databaseId = context.getStringAttribute("databaseId");
String id = context.getStringAttribute("id");
id = builderAssistant.applyCurrentNamespace(id, false);
if (databaseIdMatchesCurrent(id, databaseId, requiredDatabaseId)) {
// configuration的databaseId匹配context的databaseId
// 添加到sqlFragments
sqlFragments.put(id, context);
}
}
}
解析"/mapper/select|insert|update|delete"元素
/** XMLMapperBuilder.java */
private void buildStatementFromContext(List<XNode> list) {
if (configuration.getDatabaseId() != null) {
buildStatementFromContext(list, configuration.getDatabaseId());
}
buildStatementFromContext(list, null);
}

private void buildStatementFromContext(List<XNode> list, String requiredDatabaseId) {
for (XNode context : list) {
final XMLStatementBuilder statementParser = new XMLStatementBuilder(configuration, builderAssistant, context, requiredDatabaseId);
try {
statementParser.parseStatementNode();
} catch (IncompleteElementException e) {
configuration.addIncompleteStatement(statementParser);
}
}
}

/** XMLStatementBuilder.java */
// 解析MappedStatement
public void parseStatementNode() {
String id = context.getStringAttribute("id");
String databaseId = context.getStringAttribute("databaseId");

if (!databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) {
return;
}

Integer fetchSize = context.getIntAttribute("fetchSize");
Integer timeout = context.getIntAttribute("timeout");
String parameterMap = context.getStringAttribute("parameterMap");
String parameterType = context.getStringAttribute("parameterType");
Class<?> parameterTypeClass = resolveClass(parameterType);
String resultMap = context.getStringAttribute("resultMap");
String resultType = context.getStringAttribute("resultType");
String lang = context.getStringAttribute("lang");
// 获取LanguageDriver实例
LanguageDriver langDriver = getLanguageDriver(lang);

Class<?> resultTypeClass = resolveClass(resultType);
String resultSetType = context.getStringAttribute("resultSetType");
StatementType statementType = StatementType.valueOf(context.getStringAttribute("statementType", StatementType.PREPARED.toString()));
ResultSetType resultSetTypeEnum = resolveResultSetType(resultSetType);

String nodeName = context.getNode().getNodeName();
SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));

// 默认:对于Select语句,flushCache为false,useCache为true,即读取缓存且不clear;非Select语句则相反
boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
boolean flushCache = context.getBooleanAttribute("flushCache", !isSelect);
boolean useCache = context.getBooleanAttribute("useCache", isSelect);

boolean resultOrdered = context.getBooleanAttribute("resultOrdered", false);

// Include Fragments before parsing
XMLIncludeTransformer includeParser = new XMLIncludeTransformer(configuration, builderAssistant);
includeParser.applyIncludes(context.getNode());

// Parse selectKey after includes and remove them.
processSelectKeyNodes(id, parameterTypeClass, langDriver);

// Parse the SQL (pre: <selectKey> and <include> were parsed and removed)
SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass);
String resultSets = context.getStringAttribute("resultSets");
String keyProperty = context.getStringAttribute("keyProperty");
String keyColumn = context.getStringAttribute("keyColumn");
KeyGenerator keyGenerator;
String keyStatementId = id + SelectKeyGenerator.SELECT_KEY_SUFFIX;
keyStatementId = builderAssistant.applyCurrentNamespace(keyStatementId, true);
if (configuration.hasKeyGenerator(keyStatementId)) {
keyGenerator = configuration.getKeyGenerator(keyStatementId);
} else {
// 生成keyGenerator
keyGenerator = context.getBooleanAttribute("useGeneratedKeys",
configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType))
? new Jdbc3KeyGenerator() : new NoKeyGenerator();
}

// 构建MappedStatement
builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,
fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,
resultSetTypeEnum, flushCache, useCache, resultOrdered,
keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);
}

private LanguageDriver getLanguageDriver(String lang) {
Class<?> langClass = null;
if (lang != null) {
langClass = resolveClass(lang);
}
return builderAssistant.getLanguageDriver(langClass);
}

/** MapperBuilderAssistant.java */
public LanguageDriver getLanguageDriver(Class<?> langClass) {
if (langClass != null) {
configuration.getLanguageRegistry().register(langClass);
} else {
// 获取默认的driverClass:class org.apache.ibatis.scripting.xmltags.XMLLanguageDriver
langClass = configuration.getLanguageRegistry().getDefaultDriverClass();
}
// 返回LanguageDriver实例
return configuration.getLanguageRegistry().getDriver(langClass);
}

/** XMLLanguageDriver.java */
public SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType) {
XMLScriptBuilder builder = new XMLScriptBuilder(configuration, script, parameterType);
return builder.parseScriptNode();
}

/** XMLScriptBuilder.java */
public SqlSource parseScriptNode() {
// 获取sql语句
List<SqlNode> contents = parseDynamicTags(context);
MixedSqlNode rootSqlNode = new MixedSqlNode(contents);
SqlSource sqlSource = null;
if (isDynamic) {
sqlSource = new DynamicSqlSource(configuration, rootSqlNode);
} else {
// 包装为RawSqlSource
sqlSource = new RawSqlSource(configuration, rootSqlNode, parameterType);
}
return sqlSource;
}

List<SqlNode> parseDynamicTags(XNode node) {
List<SqlNode> contents = new ArrayList<SqlNode>();
NodeList children = node.getNode().getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
XNode child = node.newXNode(children.item(i));
// Node.TEXT_NODE表明为sql语句
if (child.getNode().getNodeType() == Node.CDATA_SECTION_NODE || child.getNode().getNodeType() == Node.TEXT_NODE) {
// 获取源sql语句
String data = child.getStringBody("");
// 将源sql语句包装为TextSqlNode
TextSqlNode textSqlNode = new TextSqlNode(data);
if (textSqlNode.isDynamic()) { // 检测源sql语句是否包含"${...}"动态表达式
contents.add(textSqlNode);
isDynamic = true;
} else {
// 直接将源sql语句包装为StaticTextSqlNode
contents.add(new StaticTextSqlNode(data));
}
} else if (child.getNode().getNodeType() == Node.ELEMENT_NODE) { // issue #628
String nodeName = child.getNode().getNodeName();
NodeHandler handler = nodeHandlers(nodeName);
if (handler == null) {
throw new BuilderException("Unknown element <" + nodeName + "> in SQL statement.");
}
handler.handleNode(child, contents);
isDynamic = true;
}
}
return contents;
}

/** RawSqlSource.java */
public RawSqlSource(Configuration configuration, SqlNode rootSqlNode, Class<?> parameterType) {
this(configuration, getSql(configuration, rootSqlNode), parameterType);
}

public RawSqlSource(Configuration configuration, String sql, Class<?> parameterType) {
SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
Class<?> clazz = parameterType == null ? Object.class : parameterType;
sqlSource = sqlSourceParser.parse(sql, clazz, new HashMap<String, Object>());
}

// 获取rootSqlNode中的sql语句
private static String getSql(Configuration configuration, SqlNode rootSqlNode) {
DynamicContext context = new DynamicContext(configuration, null);
// 用sqlBuilder组件sql语句
rootSqlNode.apply(context);
// 获取sql语句
return context.getSql();
}

/** MixedSqlNode.java */
public boolean apply(DynamicContext context) {
for (SqlNode sqlNode : contents) {
sqlNode.apply(context);
}
return true;
}

/** StaticTextSqlNode.java */
public boolean apply(DynamicContext context) {
context.appendSql(text);
return true;
}

/** DynamicContext.java */
public void appendSql(String sql) {
sqlBuilder.append(sql);
sqlBuilder.append(" ");
}

public String getSql() {
return sqlBuilder.toString().trim();
}

/** SqlSourceBuilder.java */
public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {
ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType, additionalParameters);
GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);
// 用"?"代替originalSql中的"#{...}"表达式
String sql = parser.parse(originalSql);
// 解析为StaticSqlSource
return new StaticSqlSource(configuration, sql, handler.getParameterMappings());
}

public MappedStatement addMappedStatement(
String id,
SqlSource sqlSource,
StatementType statementType,
SqlCommandType sqlCommandType,
Integer fetchSize,
Integer timeout,
String parameterMap,
Class<?> parameterType,
String resultMap,
Class<?> resultType,
ResultSetType resultSetType,
boolean flushCache,
boolean useCache,
boolean resultOrdered,
KeyGenerator keyGenerator,
String keyProperty,
String keyColumn,
String databaseId,
LanguageDriver lang,
String resultSets) {

if (unresolvedCacheRef) {
throw new IncompleteElementException("Cache-ref not yet resolved");
}

id = applyCurrentNamespace(id, false);
boolean isSelect = sqlCommandType == SqlCommandType.SELECT;

// 构建MappedStatement
MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, id, sqlSource, sqlCommandType);
statementBuilder.resource(resource);
statementBuilder.fetchSize(fetchSize);
statementBuilder.statementType(statementType);
statementBuilder.keyGenerator(keyGenerator);
statementBuilder.keyProperty(keyProperty);
statementBuilder.keyColumn(keyColumn);
statementBuilder.databaseId(databaseId);
statementBuilder.lang(lang);
statementBuilder.resultOrdered(resultOrdered);
statementBuilder.resulSets(resultSets);
setStatementTimeout(timeout, statementBuilder);

setStatementParameterMap(parameterMap, parameterType, statementBuilder);
setStatementResultMap(resultMap, resultType, resultSetType, statementBuilder);
setStatementCache(isSelect, flushCache, useCache, currentCache, statementBuilder);

MappedStatement statement = statementBuilder.build();
// 添加到configuration
configuration.addMappedStatement(statement);
return statement;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息