mybatis的基础使用类似下面的代码
public static void main(String[] args) throws IOException {
InputStream is = Resources.getResourceAsStream("");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = sqlSessionFactory.openSession();
PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
mapper.findAll();
sqlSession.close();
}
这一篇分析mybatis构建SqlSessionFactory的源码分析,其中包括创建SqlSessionFactory和其相关的配置文件,mapper的解析,本篇有点长
使用了builder构造SqlSessionFactory //org.apache.ibatis.session.SqlSessionFactoryBuilder#build(java.io.InputStream)
public SqlSessionFactory build(InputStream inputStream) {
return build(inputStream, null, null);
}
//org.apache.ibatis.session.SqlSessionFactoryBuilder#build
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
//创建一个解析器,用来解析配置文件,sql的xml文件
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
//解析xml文件,并且构建SqlSessionFactory
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.
}
}
}
//org.apache.ibatis.session.SqlSessionFactoryBuilder#build
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
//org.apache.ibatis.session.defaults.DefaultSqlSessionFactory
private final Configuration configuration;
public DefaultSqlSessionFactory(Configuration configuration) {
this.configuration = configuration;
}
配置文件的解析
创建解析器
//org.apache.ibatis.builder.xml.XMLConfigBuilder#XMLConfigBuilder
public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
}
private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
super(new Configuration());
ErrorContext.instance().resource("SQL Mapper Configuration");
this.configuration.setVariables(props);
this.parsed = false;
this.environment = environment;
this.parser = parser;
}
//调用XMLConfigBuilder抽象父类baseBuilder的构造器
//org.apache.ibatis.builder.baseBuilder#baseBuilder
//这个类只有这三个属性
public baseBuilder(Configuration configuration) {
this.configuration = configuration;
this.typeAliasRegistry = this.configuration.getTypeAliasRegistry();
this.typeHandlerRegistry = this.configuration.getTypeHandlerRegistry();
}
创建Configration,Configration的构造器以及一些属性
//Configration的一些属性 //mybatis环境 protected Environment environment; //用来生成mapper protected final MapperRegistry mapperRegistry = new MapperRegistry(this); //拦截器链,插件用拦截器实现 protected final InterceptorChain interceptorChain = new InterceptorChain(); //类型处理器注册 protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry(this); //别名注册 protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry(); protected final LanguageDriverRegistry languageRegistry = new LanguageDriverRegistry(); //sql配置 protected final Map解析xml文件mappedStatements = new StrictMap ("Mapped Statements collection") .conflictMessageProducer((savedValue, targetValue) -> ". please check " + savedValue.getResource() + " and " + targetValue.getResource()); //缓存 protected final Map caches = new StrictMap<>("Caches collection"); //结果集 protected final Map resultMaps = new StrictMap<>("Result Maps collection"); //参数集 protected final Map parameterMaps = new StrictMap<>("Parameter Maps collection"); //主键生成器 protected final Map keyGenerators = new StrictMap<>("Key Generators collection"); protected final Set loadedResources = new HashSet<>(); protected final Map sqlFragments = new StrictMap<>("XML fragments parsed from previous mappers"); protected final Collection incompleteStatements = new linkedList<>(); protected final Collection incompleteCacheRefs = new linkedList<>(); protected final Collection incompleteResultMaps = new linkedList<>(); protected final Collection incompleteMethods = new linkedList<>(); //Configration构造器 public Configuration() { // 为类型注册别名 typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class); typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class); typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class); typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class); typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class); typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class); typeAliasRegistry.registerAlias("FIFO", FifoCache.class); typeAliasRegistry.registerAlias("LRU", LruCache.class); typeAliasRegistry.registerAlias("SOFT", SoftCache.class); typeAliasRegistry.registerAlias("WEAK", WeakCache.class); typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class); typeAliasRegistry.registerAlias("XML", XMLLanguageDriver.class); typeAliasRegistry.registerAlias("RAW", RawLanguageDriver.class); typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class); typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class); typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class); typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class); typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class); typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class); typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class); typeAliasRegistry.registerAlias("CGLIB", CglibProxyFactory.class); typeAliasRegistry.registerAlias("JAVASSIST", JavassistProxyFactory.class); languageRegistry.setDefaultDriverClass(XMLLanguageDriver.class); languageRegistry.register(RawLanguageDriver.class); }
//org.apache.ibatis.builder.xml.XMLConfigBuilder#parse
public Configuration parse() {
//解析过了,抛异常
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
//标记已经解析过了
parsed = true;
//解析配置,传入根元素
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
解析配置
//org.apache.ibatis.builder.xml.XMLConfigBuilder#parseConfiguration
private void parseConfiguration(XNode root) {
try {
//解析配置文件各种标签
propertiesElement(root.evalNode("properties"));
//解析setting标签
Properties settings = settingsAsProperties(root.evalNode("settings"));
loadCustomVfs(settings);
//解析别名
typeAliasesElement(root.evalNode("typeAliases"));
//解析插件
pluginElement(root.evalNode("plugins"));
//解析对象工厂
objectFactoryElement(root.evalNode("objectFactory"));
//对象加工
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
//反射
reflectorFactoryElement(root.evalNode("reflectorFactory"));
//给setting的子标签赋值
settingsElement(settings);
//创建数据源
environmentsElement(root.evalNode("environments"));
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
//解析类型处理器
typeHandlerElement(root.evalNode("typeHandlers"));
//解析mapper
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
创建数据源
//org.apache.ibatis.builder.xml.XMLConfigBuilder#environmentsElement
private void environmentsElement(XNode context) throws Exception {
if (context != null) {
if (environment == null) {
environment = context.getStringAttribute("default");
}
for (XNode child : context.getChildren()) {
String id = child.getStringAttribute("id");
if (isSpecifiedEnvironment(id)) {
// 事务工厂
TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
// 数据源工厂
DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
// 数据源
DataSource dataSource = dsFactory.getDataSource();
// 包含了 事务工厂和数据源的 Environment
Environment.Builder environmentBuilder = new Environment.Builder(id)
.transactionFactory(txFactory)
.dataSource(dataSource);
// 放入 Configuration
configuration.setEnvironment(environmentBuilder.build());
}
}
}
}
//创建数据源工厂
//org.apache.ibatis.builder.xml.XMLConfigBuilder#dataSourceElement
private DataSourceFactory dataSourceElement(XNode context) throws Exception {
if (context != null) {
//dataSource标签的子标签
String type = context.getStringAttribute("type");
Properties props = context.getChildrenAsProperties();
//根据具体类型实例化数据源工厂
DataSourceFactory factory = (DataSourceFactory) resolveClass(type).getDeclaredConstructor().newInstance();
factory.setProperties(props);
return factory;
}
throw new BuilderException("Environment declaration requires a DataSourceFactory.");
}
//获取数据源工厂的具体类型
//org.apache.ibatis.builder.baseBuilder#resolveClass
protected Class extends T> resolveClass(String alias) {
if (alias == null) {
return null;
}
try {
return resolveAlias(alias);
} catch (Exception e) {
throw new BuilderException("Error resolving class. Cause: " + e, e);
}
}
//从别名注册器中获取具体的类型
//org.apache.ibatis.builder.baseBuilder#resolveAlias
protected Class extends T> resolveAlias(String alias) {
return typeAliasRegistry.resolveAlias(alias);
}
解析typeHandlers标签,注册typeHandler
//org.apache.ibatis.builder.xml.XMLConfigBuilder#typeHandlerElement
private void typeHandlerElement(XNode parent) {
if (parent != null) {
for (XNode child : parent.getChildren()) {
if ("package".equals(child.getName())) {
String typeHandlerPackage = child.getStringAttribute("name");
typeHandlerRegistry.register(typeHandlerPackage);
} else {
//Java类型名称
String javaTypeName = child.getStringAttribute("javaType");
//jdbc类型名称
String jdbcTypeName = child.getStringAttribute("jdbcType");
//类型处理器名称
String handlerTypeName = child.getStringAttribute("handler");
Class> javaTypeClass = resolveClass(javaTypeName);
JdbcType jdbcType = resolveJdbcType(jdbcTypeName);
Class> typeHandlerClass = resolveClass(handlerTypeName);
if (javaTypeClass != null) {
//注册类型处理器
if (jdbcType == null) {
typeHandlerRegistry.register(javaTypeClass, typeHandlerClass);
} else {
typeHandlerRegistry.register(javaTypeClass, jdbcType, typeHandlerClass);
}
} else {
typeHandlerRegistry.register(typeHandlerClass);
}
}
}
}
}
解析mapper
//org.apache.ibatis.builder.xml.XMLConfigBuilder#mapperElement
private void mapperElement(XNode parent) throws Exception {
if (parent != null) {
for (XNode child : parent.getChildren()) {
// package 包
if ("package".equals(child.getName())) {
String mapperPackage = child.getStringAttribute("name");
configuration.addMappers(mapperPackage);
} else {
String resource = child.getStringAttribute("resource");
String url = child.getStringAttribute("url");
String mapperClass = child.getStringAttribute("class");
if (resource != null && url == null && mapperClass == null) {
// resource 相对路径
ErrorContext.instance().resource(resource);
InputStream inputStream = Resources.getResourceAsStream(resource);
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
// 解析 Mapper.xml,总体上做了两件事情 >>
mapperParser.parse();
} else if (resource == null && url != null && mapperClass == null) {
// 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) {
// class 单个接口
Class> mapperInterface = Resources.classForName(mapperClass);
configuration.addMapper(mapperInterface);
} else {
throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
}
}
}
}
}
根据包名注册mapper
//org.apache.ibatis.session.Configuration#addMappers(java.lang.String)
public void addMappers(String packageName) {
mapperRegistry.addMappers(packageName);
}
//org.apache.ibatis.binding.MapperRegistry#addMappers(java.lang.String)
public void addMappers(String packageName) {
addMappers(packageName, Object.class);
}
//org.apache.ibatis.binding.MapperRegistry#addMappers
public void addMappers(String packageName, Class> superType) {
ResolverUtil> resolverUtil = new ResolverUtil<>();
resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
//从包中获取所有的mapper
Set>> mapperSet = resolverUtil.getClasses();
// 循环添加
for (Class> mapperClass : mapperSet) {
addMapper(mapperClass);
}
}
添加mapper
//org.apache.ibatis.binding.MapperRegistry#addMapper public解析mappervoid addMapper(Class type) { //只有接口才会被处理 if (type.isInterface()) { //已经添加过该mapper了 if (hasMapper(type)) { throw new BindingException("Type " + type + " is already known to the MapperRegistry."); } boolean loadCompleted = false; try { //private final Map , MapperProxyFactory>> knownMappers = new HashMap<>(); //存放的是接口类型,和对应的工厂类的关系 knownMappers.put(type, new MapperProxyFactory<>(type)); //mapper类型注册应该早于mapper的解析 // 注册了接口之后,根据接口,开始解析所有方法上的注解,例如 @Select >> MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type); parser.parse(); loadCompleted = true; } finally { if (!loadCompleted) { knownMappers.remove(type); } } } }
//org.apache.ibatis.builder.annotation.MapperAnnotationBuilder#parse
public void parse() {
String resource = type.toString();
if (!configuration.isResourceLoaded(resource)) {
// 先判断 Mapper.xml 有没有解析,没有的话先解析 Mapper.xml(例如定义 package 方式)
loadXmlResource();
configuration.addLoadedResource(resource);
assistant.setCurrentNamespace(type.getName());
// 处理 @CacheNamespace
parseCache();
// 处理 @CacheNamespaceRef
parseCacheRef();
// 获取所有方法
Method[] methods = type.getMethods();
for (Method method : methods) {
try {
// issue #237
if (!method.isBridge()) {
// 解析方法上的注解,添加到 MappedStatement 集合中 >>
parseStatement(method);
}
} catch (IncompleteElementException e) {
configuration.addIncompleteMethod(new MethodResolver(this, method));
}
}
}
parsePendingMethods();
}
加载mapper.xml资源
//org.apache.ibatis.builder.annotation.MapperAnnotationBuilder#loadXmlResource
private void loadXmlResource() {
// Spring 不知道真正的资源名字,所以添加了一个标志防止资源被加载两次
// 标记在这里 XMLMapperBuilder#bindMapperForNamespace
if (!configuration.isResourceLoaded("namespace:" + type.getName())) {
String xmlResource = type.getName().replace('.', '/') + ".xml";
// #1347 加载mapper.xml
InputStream inputStream = type.getResourceAsStream("/" + xmlResource);
if (inputStream == null) {
// 从classpath下加载mapper.xml
try {
inputStream = Resources.getResourceAsStream(type.getClassLoader(), xmlResource);
} catch (IOException e2) {
// ignore, resource is not required
}
}
if (inputStream != null) {
//构建mapper解析器
XMLMapperBuilder xmlParser = new XMLMapperBuilder(inputStream, assistant.getConfiguration(), xmlResource, configuration.getSqlFragments(), type.getName());
// 解析 Mapper.xml >>
xmlParser.parse();
}
}
}
解析mappe.xml
//org.apache.ibatis.builder.xml.XMLMapperBuilder#parse
public void parse() {
// 资源还没有被加载
//protected final Set loadedResources = new HashSet<>();
if (!configuration.isResourceLoaded(resource)) {
// 具体增删改查标签的解析。 一个标签一个MappedStatement
configurationElement(parser.evalNode("/mapper"));
//标记该资源已经被加载
configuration.addLoadedResource(resource);
// 2、把namespace(接口类型)和工厂类绑定起来,放到一个map。
// 一个namespace 一个 MapperProxyFactory >>
bindMapperForNamespace();
}
parsePendingResultMaps();
parsePendingCacheRefs();
parsePendingStatements();
}
解析mapper标签
private void configurationElement(XNode context) {
try {
//解析namespace
String namespace = context.getStringAttribute("namespace");
if (namespace == null || namespace.equals("")) {
throw new BuilderException("Mapper's namespace cannot be empty");
}
builderAssistant.setCurrentNamespace(namespace);
// 添加缓存对象
cacheRefElement(context.evalNode("cache-ref"));
// 解析 cache 属性,添加缓存对象
cacheElement(context.evalNode("cache"));
// 创建 ParameterMapping 对象
parameterMapElement(context.evalNodes("/mapper/parameterMap"));
// 创建 List
resultMapElements(context.evalNodes("/mapper/resultMap"));
// 解析可以复用的SQL
sqlElement(context.evalNodes("/mapper/sql"));
// 解析增删改查标签,得到 MappedStatement
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);
}
}
创建 ParameterMapping 对象
//org.apache.ibatis.builder.xml.XMLMapperBuilder#parameterMapElement private void parameterMapElement(List创建resultMappingslist) { for (XNode parameterMapNode : list) { //获取id String id = parameterMapNode.getStringAttribute("id"); //获取type String type = parameterMapNode.getStringAttribute("type"); //解析type对应的类 Class> parameterClass = resolveClass(type); //获取参数类型 List parameterNodes = parameterMapNode.evalNodes("parameter"); List parameterMappings = new ArrayList<>(); //循环遍历所有的参数 for (XNode parameterNode : parameterNodes) { //获取属性名称 String property = parameterNode.getStringAttribute("property"); //获取Java类型 String javaType = parameterNode.getStringAttribute("javaType"); //获取jdbc类型 String jdbcType = parameterNode.getStringAttribute("jdbcType"); //获取resultMap的名称 String resultMap = parameterNode.getStringAttribute("resultMap"); //获取模式 String mode = parameterNode.getStringAttribute("mode"); //获取类型处理器 String typeHandler = parameterNode.getStringAttribute("typeHandler"); Integer numericScale = parameterNode.getIntAttribute("numericScale"); //解析模式枚举 IN, OUT, INOUT ParameterMode modeEnum = resolveParameterMode(mode); //解析Java类型的类 Class> javaTypeClass = resolveClass(javaType); //解析jdbc类型的类 JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType); //解析类型处理器的类 Class extends TypeHandler>> typeHandlerClass = resolveClass(typeHandler); //建立parameterMapping并加入parameterMappings ParameterMapping parameterMapping = builderAssistant.buildParameterMapping(parameterClass, property, javaTypeClass, jdbcTypeEnum, resultMap, modeEnum, typeHandlerClass, numericScale); parameterMappings.add(parameterMapping); } builderAssistant.addParameterMap(id, parameterClass, parameterMappings); } } //添加parameterMap //protected final Map parameterMaps = new StrictMap<>("Parameter Maps collection"); //org.apache.ibatis.builder.MapperBuilderAssistant#addParameterMap public ParameterMap addParameterMap(String id, Class> parameterClass, List parameterMappings) { id = applyCurrentNamespace(id, false); ParameterMap parameterMap = new ParameterMap.Builder(configuration, id, parameterClass, parameterMappings).build(); configuration.addParameterMap(parameterMap); return parameterMap; }
//org.apache.ibatis.builder.xml.XMLMapperBuilder#resultMapElements private void resultMapElements(List创建Statementlist) { for (XNode resultMapNode : list) { try { resultMapElement(resultMapNode); } catch (IncompleteElementException e) { // ignore, it will be retried } } } //org.apache.ibatis.builder.xml.XMLMapperBuilder#resultMapElement private ResultMap resultMapElement(XNode resultMapNode) { return resultMapElement(resultMapNode, Collections.emptyList(), null); } //org.apache.ibatis.builder.xml.XMLMapperBuilder#resultMapElement private ResultMap resultMapElement(XNode resultMapNode, List additionalResultMappings, Class> enclosingType) { ErrorContext.instance().activity("processing " + resultMapNode.getValuebasedIdentifier()); //获取四中之一的名称 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 resultMappings = new ArrayList<>(additionalResultMappings); List resultChildren = resultMapNode.getChildren(); //循环遍历子节点 for (XNode resultChild : resultChildren) { if ("constructor".equals(resultChild.getName())) { processConstructorElement(resultChild, typeClass, resultMappings); } else if ("discriminator".equals(resultChild.getName())) { discriminator = processDiscriminatorElement(resultChild, typeClass, resultMappings); } else { List flags = new ArrayList<>(); if ("id".equals(resultChild.getName())) { flags.add(ResultFlag.ID); } //构建resuntMapping并添加到resultMappings resultMappings.add(buildResultMappingFromContext(resultChild, typeClass, flags)); } } //获取id String id = resultMapNode.getStringAttribute("id", resultMapNode.getValuebasedIdentifier()); String extend = resultMapNode.getStringAttribute("extends"); Boolean autoMapping = resultMapNode.getBooleanAttribute("autoMapping"); //生成resultMapping解析器 ResultMapResolver resultMapResolver = new ResultMapResolver(builderAssistant, id, typeClass, extend, discriminator, resultMappings, autoMapping); try { return resultMapResolver.resolve(); } catch (IncompleteElementException e) { configuration.addIncompleteResultMap(resultMapResolver); throw e; } } //org.apache.ibatis.builder.ResultMapResolver#resolve public ResultMap resolve() { return assistant.addResultMap(this.id, this.type, this.extend, this.discriminator, this.resultMappings, this.autoMapping); } //添加resultMap //org.apache.ibatis.builder.MapperBuilderAssistant#addResultMap public ResultMap addResultMap( String id, Class> type, String extend, Discriminator discriminator, List resultMappings, Boolean autoMapping) { id = applyCurrentNamespace(id, false); extend = applyCurrentNamespace(extend, true); if (extend != null) { if (!configuration.hasResultMap(extend)) { throw new IncompleteElementException("Could not find a parent resultmap with id '" + extend + "'"); } ResultMap resultMap = configuration.getResultMap(extend); List extendedResultMappings = new ArrayList<>(resultMap.getResultMappings()); 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) { extendedResultMappings.removeIf(resultMapping -> resultMapping.getFlags().contains(ResultFlag.CONSTRUCTOR)); } resultMappings.addAll(extendedResultMappings); } ResultMap resultMap = new ResultMap.Builder(configuration, id, type, resultMappings, autoMapping) .discriminator(discriminator) .build(); configuration.addResultMap(resultMap); return resultMap; } //org.apache.ibatis.session.Configuration#addResultMap //protected final Map resultMaps = new StrictMap<>("Result Maps collection"); public void addResultMap(ResultMap rm) { resultMaps.put(rm.getId(), rm); checkLocallyForDiscriminatedNestedResultMaps(rm); checkGloballyForDiscriminatedNestedResultMaps(rm); }
//org.apache.ibatis.builder.xml.XMLMapperBuilder#buildStatementFromContext private void buildStatementFromContext(Listlist) { if (configuration.getDatabaseId() != null) { buildStatementFromContext(list, configuration.getDatabaseId()); } // 解析 Statement buildStatementFromContext(list, null); } //org.apache.ibatis.builder.xml.XMLMapperBuilder#buildStatementFromContext private void buildStatementFromContext(List list, String requiredDatabaseId) { for (XNode context : list) { // 用来解析增删改查标签的 XMLStatementBuilder final XMLStatementBuilder statementParser = new XMLStatementBuilder(configuration, builderAssistant, context, requiredDatabaseId); try { // 解析 Statement,添加 MappedStatement 对象 statementParser.parseStatementNode(); } catch (IncompleteElementException e) { configuration.addIncompleteStatement(statementParser); } } } //org.apache.ibatis.builder.xml.XMLStatementBuilder#parseStatementNode public void parseStatementNode() { //获取id String id = context.getStringAttribute("id"); //获取databaseId String databaseId = context.getStringAttribute("databaseId"); if (!databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) { return; } String nodeName = context.getNode().getNodeName(); //获取sql类型 SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH)); //是否是查询语句 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()); //参数类型 String parameterType = context.getStringAttribute("parameterType"); //解析参数类型 Class> parameterTypeClass = resolveClass(parameterType); //语言 String lang = context.getStringAttribute("lang"); LanguageDriver langDriver = getLanguageDriver(lang); // 解析selectkey,之后是用并删除 processSelectKeyNodes(id, parameterTypeClass, langDriver); // 解析sql KeyGenerator keyGenerator; String keyStatementId = id + SelectKeyGenerator.SELECT_KEY_SUFFIX; keyStatementId = builderAssistant.applyCurrentNamespace(keyStatementId, true); if (configuration.hasKeyGenerator(keyStatementId)) { keyGenerator = configuration.getKeyGenerator(keyStatementId); } else { keyGenerator = context.getBooleanAttribute("useGeneratedKeys", configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType)) ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE; } SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass); //statement的类型,默认PreparedStatement StatementType statementType = StatementType.valueOf(context.getStringAttribute("statementType", StatementType.PREPARED.toString())); Integer fetchSize = context.getIntAttribute("fetchSize"); Integer timeout = context.getIntAttribute("timeout"); String parameterMap = context.getStringAttribute("parameterMap"); String resultType = context.getStringAttribute("resultType"); Class> resultTypeClass = resolveClass(resultType); String resultMap = context.getStringAttribute("resultMap"); String resultSetType = context.getStringAttribute("resultSetType"); ResultSetType resultSetTypeEnum = resolveResultSetType(resultSetType); if (resultSetTypeEnum == null) { resultSetTypeEnum = configuration.getDefaultResultSetType(); } //主键的名称 String keyProperty = context.getStringAttribute("keyProperty"); //主键的列名 String keyColumn = context.getStringAttribute("keyColumn"); String resultSets = context.getStringAttribute("resultSets"); // 创建 MappedStatement builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType, fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass, resultSetTypeEnum, flushCache, useCache, resultOrdered, keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets); } //org.apache.ibatis.builder.MapperBuilderAssistant#addMappedStatement 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.Builder MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, id, sqlSource, sqlCommandType) .resource(resource) .fetchSize(fetchSize) .timeout(timeout) .statementType(statementType) .keyGenerator(keyGenerator) .keyProperty(keyProperty) .keyColumn(keyColumn) .databaseId(databaseId) .lang(lang) .resultOrdered(resultOrdered) .resultSets(resultSets) .resultMaps(getStatementResultMaps(resultMap, resultType, id)) .resultSetType(resultSetType) .flushCacheRequired(valueOrDefault(flushCache, !isSelect)) .useCache(valueOrDefault(useCache, isSelect)) .cache(currentCache); ParameterMap statementParameterMap = getStatementParameterMap(parameterMap, parameterType, id); if (statementParameterMap != null) { statementBuilder.parameterMap(statementParameterMap); } //构建MappedStatement MappedStatement statement = statementBuilder.build(); // 在 Configuration 添加 MappedStatement configuration.addMappedStatement(statement); return statement; } //org.apache.ibatis.session.Configuration#addMappedStatement //protected final Map mappedStatements = new StrictMap ("Mapped Statements collection") .conflictMessageProducer((savedValue, targetValue) -> ". please check " + savedValue.getResource() + " and " + targetValue.getResource()); public void addMappedStatement(MappedStatement ms) { mappedStatements.put(ms.getId(), ms); }



