0%

mybatis初始化

mybatis初始化

mybatis的初始化实际上是解析xml配置文件构建SqlSessionFactory的过程

1
2
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatis-config.xml");
return new SqlSessionFactoryBuilder().build(is);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
// 生成XPathParser对象,构建dom树,用于解析配置文件
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
// parser.parse()将配置文件信息解析构建Configuration对象
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}

parser.parse()将配置文件信息解析构建Configuration对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
//从XPathParser中取出 <configuration>节点对应的Node对象,然后解析此Node节点的子Node
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}


private void parseConfiguration(XNode root) {
try {
// issue #117 read properties first
// 解析properties节点
propertiesElement(root.evalNode("properties"));
// 解析settings节点
Properties settings = settingsAsProperties(root.evalNode("settings"));
loadCustomVfs(settings);
loadCustomLogImpl(settings);
// 解析typeAliases节点
typeAliasesElement(root.evalNode("typeAliases"));
// 解析plugins节点
pluginElement(root.evalNode("plugins"));
// 解析objectFactory节点
objectFactoryElement(root.evalNode("objectFactory"));
// 解析objectWrapperFactory节点
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
// 解析reflectorFactory节点
reflectorFactoryElement(root.evalNode("reflectorFactory"));
settingsElement(settings);
// read it after objectFactory and objectWrapperFactory issue #631
// 解析typeAliases节点
environmentsElement(root.evalNode("environments"));
// 解析environments节点
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
// 解析typeHandlers节点
typeHandlerElement(root.evalNode("typeHandlers"));
// 解析mappers节点
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}

解析mapper.xml

1
2
// 解析mappers节点
mapperElement(root.evalNode("mappers"));

通过解析mappers来获取mapper.xml,进而进行解析mapper.xml

1
2
3
4
5
6
7
8
9
10
11
12
public void parse() {
if (!configuration.isResourceLoaded(resource)) {
// 解析mapper
configurationElement(parser.evalNode("/mapper"));
configuration.addLoadedResource(resource);
bindMapperForNamespace();
}

parsePendingResultMaps();
parsePendingCacheRefs();
parsePendingStatements();
}

解析mapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private void configurationElement(XNode context) {
try {
// namespace属性
String namespace = context.getStringAttribute("namespace");
if (namespace == null || namespace.isEmpty()) {
throw new BuilderException("Mapper's namespace cannot be empty");
}
builderAssistant.setCurrentNamespace(namespace);
// cache-ref节点
cacheRefElement(context.evalNode("cache-ref"));
// cache节点
cacheElement(context.evalNode("cache"));
// parameterMap节点
parameterMapElement(context.evalNodes("/mapper/parameterMap"));
// resultMap节点
resultMapElements(context.evalNodes("/mapper/resultMap"));
// sql节点
sqlElement(context.evalNodes("/mapper/sql"));
// select|insert|update|delete节点
buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
} catch (Exception e) {
throw new BuilderException("Error parsing Mapper XML. The XML location is '" + resource + "'. Cause: " + e, e);
}
}
解析resultMap节点
1
2
 // resultMap节点
resultMapElements(context.evalNodes("/mapper/resultMap"));

将resultMap节点解析为ResultMap对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
private ResultMap resultMapElement(XNode resultMapNode, List<ResultMapping> additionalResultMappings, Class<?> enclosingType) {
ErrorContext.instance().activity("processing " + resultMapNode.getValueBasedIdentifier());
// 获取type属性,结果集所对应的类型名称
String type = resultMapNode.getStringAttribute("type",
resultMapNode.getStringAttribute("ofType",
resultMapNode.getStringAttribute("resultType",
resultMapNode.getStringAttribute("javaType"))));
// 通过反射获取所对应的类型
Class<?> typeClass = resolveClass(type);
if (typeClass == null) {
typeClass = inheritEnclosingType(resultMapNode, enclosingType);
}
Discriminator discriminator = null;
// 记录解析结果
List<ResultMapping> resultMappings = new ArrayList<>(additionalResultMappings);
// 处理子节点
List<XNode> resultChildren = resultMapNode.getChildren();
for (XNode resultChild : resultChildren) {
// constructor节点
if ("constructor".equals(resultChild.getName())) {
// 解析构造器元素
processConstructorElement(resultChild, typeClass, resultMappings);
} else if ("discriminator".equals(resultChild.getName())) {
discriminator = processDiscriminatorElement(resultChild, typeClass, resultMappings);
} else {
List<ResultFlag> flags = new ArrayList<>();
// 主键标识
if ("id".equals(resultChild.getName())) {
flags.add(ResultFlag.ID);
}
// 创建resultMapping对象,并加入到resultMappings中
resultMappings.add(buildResultMappingFromContext(resultChild, typeClass, flags));
}
}
// 获取resultMap的id属性,如果没有的话使用resultMapNode.getValueBasedIdentifier()设置默认值,先取id属性,id属性没有取value属性,value属性没有取property属性
String id = resultMapNode.getStringAttribute("id",
resultMapNode.getValueBasedIdentifier());
// 获取resultMap的extends属性,表示结果集的继承
String extend = resultMapNode.getStringAttribute("extends");
// 自动映射属性,将列名自动映射为属性
Boolean autoMapping = resultMapNode.getBooleanAttribute("autoMapping");
// 创建ResultMapResolver对象,用于解析resultMappings生成ResultMap对象
ResultMapResolver resultMapResolver = new ResultMapResolver(builderAssistant, id, typeClass, extend, discriminator, resultMappings, autoMapping);
try {
return resultMapResolver.resolve();
} catch (IncompleteElementException e) {
// 其内包含有还没有解析到的resultMap节点
// 如果无法创建resultMap对象,则将结果添加到incompleteResultMaps集合中,表示未完成的结果集
configuration.addIncompleteResultMap(resultMapResolver);
throw e;
}
}