/**
- 解析 <mapper url
/
ErrorContext.instance().resource(url);
InputStream inputStream = Resources.getUrlAsStream(url);
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
mapperParser.parse();
} else if (resource == null && url == null && mapperClass != null) {
/* - 解析 <mapper class
/
Class<?> mapperInterface = Resources.classForName(mapperClass);
configuration.addMapper(mapperInterface);
} else {
/* - 以下代码可以看出 url resource class 三个属性只能选择一个,否则就会报错
*/
throw new BuilderException(“A mapper element may only specify a url, resource or class, but not more than one.”);
}
}
}
}
}
}
1.4.2:mapperParser.parse();解析
我的UserMapper.xml文件内容为:
<?xml version="1.0" encoding="UTF-8"?> select * from `user` where userId = #{userId}UserMapper接口内容为:
package com.mapper;
import com.entity.User;
import org.apache.ibatis.annotations.Select;
public interface UserMapper {
@Select(“select * from user
where userId = 2”)
User findById(int userId);
}
疑问?UserMapper.xml有<select id=“findById”,而在接口中的findById方法我又加了一个@Select注解;那么执行会选择哪一条Sql执行还是报错呢?
以UserMapper.xml为例子解析,可以看到 resource = mapper/UserMapper.xml
public class XMLMapperBuilder extends BaseBuilder {
public void parse() {
if (!configuration.isResourceLoaded(resource)) {
/**
- 解析 mapper.xml文件内容
/
configurationElement(parser.evalNode("/mapper"));
configuration.addLoadedResource(resource);
/* - 解析 mapper.xml的
- namespace指定的{UserMapper}接口的注解信息
*/
bindMapperForNamespace();
}
parsePendingResultMaps();
parsePendingCacheRefs();
parsePendingStatements();
}
}
1.4.3:configurationElement(parser.evalNode("/mapper"));
解析 mapper.xml文件内容
public class XMLMapperBuilder extends BaseBuilder {
private void configurationElement(XNode context) {
try {
/**
- namespace属性
/
String namespace = context.getStringAttribute(“namespace”);
if (namespace == null || namespace.equals("")) {
/* - 不指定 namespace会报错哦 由此得知 namespace属性是必须指定的
/
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"));
/* - 解析 sql语句 select|insert|update|delete
- 重点分析这里,这里的解析会关联到 mapper接口的执行方法 sql语句映射
*/
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);
}
}
}
1.4.4:buildStatementFromContext(context.evalNodes(“select|insert|update|delete”));
解析 sql语句 select|insert|update|delete;list参数内容是select|insert|update|delete的Sql语句
XMLStatementBuilder Sql语句的解析器
1.4.5:stateme
《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》
【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享
ntParser.parseStatementNode();解析Sql语句
builderAssistant.addMappedStatement,并不是添加一个mapper.xml文件隐射的实例,而是为每一个Sql语句创建一个实例
public class XMLStatementBuilder extends BaseBuilder {
private final MapperBuilderAssistant builderAssistant;
public void parseStatementNode() {
/**
- 此处省略一大推代码…
/
/* - select * from
user
where userId = #{userId} - 参数解析
- id:标签指定的id = findById
- sqlSource:Sql语句,Sql参数占位
- statementType:sql执行类型 参考{@link StatementType}
-
STATEMENT: 直接操作sql,不进行预编译 ${}
-
PREPARED: 预处理,参数,进行预编译 #{}
-
CALLABLE: 执行存储过程
- sqlCommandType:sql语句类型 参考{@link SqlCommandType}
-
UNKNOWN:未知,INSERT:新增,UPDATE:修改,DELETE:删除,SELECT:查询,FLUSH:刷新
- 其他参数可查看官网:https://mybatis.org/mybatis-3/zh/sqlmap-xml.html
*/
builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,
fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,
resultSetTypeEnum, flushCache, useCache, resultOrdered,
keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);
}
}
1.4.6:builderAssistant.addMappedStatement();
创建一个MappedStatement实例添加到 Configuration.mappedStatements的Map集合中
public class XMLStatementBuilder extends BaseBuilder {
public MappedStatement addMappedStatement() {
/**
- 此处省略一大推代码…
/
MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, id, sqlSource, sqlCommandType)
/* - 建造者模式
- 用于设置 MappedStatement的属性
- 此处省略一大推代码…
*/
/**
- 设置参数入参类型 parameterType属性
- select * from
user
where userId = #{userId}
*/
ParameterMap statementParameterMap = getStatementParameterMap(parameterMap, parameterType, id);
if (statementParameterMap != null) {
statementBuilder.parameterMap(statementParameterMap);
}
/**
<