mybatis源码解析六之执行过程 绝地灬酷狼 2023-03-13 01:59 112阅读 0赞 ### 文章目录 ### * MyBatis 初始化 * * SqlSessionFactoryBuilder * BaseBuilder * XMLConfigBuilder * 解析mapper * * XMLMapperBuilder * MapperBuilderAssistant * CacheBuilder * ResultMapping * ResultMap * 解析SQL语句 * * SqlSource * MappedStatement * XMLStatementBuilder * 绑定Mapper 接口 * 处理incomplete *集合 * SqlNode&SqlSource * * OgnlCache * DynamicContext * SqlNode * TextSqlNode * IfSqlNode * TrimSqlNode * ForEachSqlNode * ChooseSqlNode * VarDeclSqlNode * 解析成BoundSql * * SqlSourceBuilder * ParameterMapping * BoundSql * SqlSource * * DynamicSqlSource * RawSqlSource * ResultSetHandler * * ResultSetHandler * DefaultResultSetHandler * 嵌套查询&延迟加载 * * ResultLoader * ResultLoaderMap * ResultExtractor * ProxyFactory * CglibProxyFactory * 调用懒加载 * 多结果集处理 * 游标 * * DefaultCursor * 存储过程中输出参数的相关处理 * KeyGenerator * * KeyGenerator * Jdbc3KeyGenerator * SelectKeyGenerator * StatementHandler * * BaseStatementHandler * DefaultParameterHandler * PreparedStatementHandler * Executor * * BaseExecutor * SimpleExecutor * ReuseExecutor * BatchExecutor * CachingExecutor * TransactionalCache * SqlSession * * DefaultSqlSession * DefaultSqlSessionFactory * SqlSessionManager # MyBatis 初始化 # ## SqlSessionFactoryBuilder ## public class SqlSessionFactoryBuilder { public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) { try { //读取配置文件 XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); //解析配置文件得到Configuration对象,创建DefaultSqlSessionFactory 对象 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. } } } public SqlSessionFactory build(Configuration config) { return new DefaultSqlSessionFactory(config); } } ## BaseBuilder ## public abstract class BaseBuilder { // Configuration 是MyBatis 初始化过程的核心对象, MyBatis 中几乎全部的配置信息会保存到 // Configuration 对象中。Configuration 对象是在MyBatis 初始化过程中创建且是全局唯一的,也有人称它是一个“ All-In-One ”配置对象 protected final Configuration configuration; //在mybatis-config . xml 配置文件中可以使用<typeAliases>标签定义别名,这些定义的别名都会记录在该 // TypeAliasRegistry 对象中 protected final TypeAliasRegistry typeAliasRegistry; // 在mybatis-config.xml 配置文件中可以使用< typeHandlers >标签添加自定义TypeHandler,完成指定数据库类型与Java 类型的转换, protected final TypeHandlerRegistry typeHandlerRegistry; } ## XMLConfigBuilder ## public class XMLConfigBuilder extends BaseBuilder { // 标识是否已经解析过mybat 工s-config.xml 配置丈件 private boolean parsed; //用于解析mybatis - config . xml 配置文件的XPathParser 对象 private final XPathParser parser; //标识< environment >配置的名称,默认读取< environment > 标签的default 属性 private String environment; // ReflectorFactory 负责创建和缓存Reflector 对象, private final ReflectorFactory localReflectorFactory = new DefaultReflectorFactory(); public Configuration parse() { if (parsed) { throw new BuilderException("Each XMLConfigBuilder can only be used once."); } parsed = true; //在mybatis-config.xml 配置文件中查找< configuration >节点,并开始解析 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")); //设置vfsimpl 字段 loadCustomVfs(settings); loadCustomLogImpl(settings); typeAliasesElement(root.evalNode("typeAliases")); pluginElement(root.evalNode("plugins")); objectFactoryElement(root.evalNode("objectFactory")); objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); reflectorFactoryElement(root.evalNode("reflectorFactory")); settingsElement(settings); // read it after objectFactory and objectWrapperFactory issue #631 //每个<environment> 节点对应一种环境的配置。 environmentsElement(root.evalNode("environments")); databaseIdProviderElement(root.evalNode("databaseIdProvider")); typeHandlerElement(root.evalNode("typeHandlers")); mapperElement(root.evalNode("mappers")); } catch (Exception e) { throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e); } } private Properties settingsAsProperties(XNode context) { if (context == null) { return new Properties(); } //解析< settings >的子节点(< setting >标签)的name 和value 属性,并返回Properties 对象 Properties props = context.getChildrenAsProperties(); // Check that all settings are known to the configuration class //创建Configurat对应的MetaClass 对象 MetaClass metaConfig = MetaClass.forClass(Configuration.class, localReflectorFactory); //检测Configuration 中是否定义了key 指定属性相应的setter 方法 for (Object key : props.keySet()) { if (!metaConfig.hasSetter(String.valueOf(key))) { throw new BuilderException("The setting " + key + " is not known. Make sure you spelled it correctly (case sensitive)."); } } return props; } private void typeAliasesElement(XNode parent) { if (parent != null) { //处理全部子节点 for (XNode child : parent.getChildren()) { //处理< package >节点 if ("package".equals(child.getName())) { // 获取指定的包名 String typeAliasPackage = child.getStringAttribute("name"); //通过TypeAliasRegistry 扫描指定包中所有的类,并解析@ Alias注解,完成别名注册 configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage); } else { //处理< typeAlias >节点 String alias = child.getStringAttribute("alias"); String type = child.getStringAttribute("type"); try { Class<?> clazz = Resources.classForName(type); if (alias == null) { // 扫描@Alias注解,完成注册 typeAliasRegistry.registerAlias(clazz); } else { // 注册别名 typeAliasRegistry.registerAlias(alias, clazz); } } catch (ClassNotFoundException e) { throw new BuilderException("Error registering typeAlias for '" + alias + "'. Cause: " + e, e); } } } } } private void pluginElement(XNode parent) throws Exception { if (parent != null) { //追历全部子节点(即< plugin>节点) for (XNode child : parent.getChildren()) { //获取<plugin>节点的interceptor 属性的值 String interceptor = child.getStringAttribute("interceptor"); //获取<plugin>节点下<properties>配置的信息,并形成Properties 对象 Properties properties = child.getChildrenAsProperties(); //通过前面介绍的TypeAliasRegistry 解析别名之后,实例化Interceptor 对象 Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).getDeclaredConstructor().newInstance(); // 设置Interceptor 的属性 interceptorInstance.setProperties(properties); // 记录Interceptor 对象 configuration.addInterceptor(interceptorInstance); } } } private void objectFactoryElement(XNode context) throws Exception { if (context != null) { //获取<objectFactory> 节点的type 属性 String type = context.getStringAttribute("type"); //获取<objectFactory>节点下配置的信息,并形成Properties对象 Properties properties = context.getChildrenAsProperties(); //进行别名解析后,实例化自定义ObjectFactory实现 ObjectFactory factory = (ObjectFactory) resolveClass(type).getDeclaredConstructor().newInstance(); //设置自定义ObjectFactory 的属性,完成初始化的相关操作 factory.setProperties(properties); //将自定义ObjectFactory 对象记录到configuration对象的objectFactory 字段中,待后续使用 configuration.setObjectFactory(factory); } } private void propertiesElement(XNode context) throws Exception { if (context != null) { //解析<properties >的子节点(<property>标签)的name 和value 属性,并记录到Properties 中 Properties defaults = context.getChildrenAsProperties(); //解析< properties >的resource 和url ,这两个属性用于确定properties 配置文件的位置 String resource = context.getStringAttribute("resource"); String url = context.getStringAttribute("url"); //resource 属性和url 属性不能同时存在,否则会抛出异常 if (resource != null && url != null) { throw new BuilderException("The properties element cannot specify both a URL and a resource based property file reference. Please specify one or the other."); } //加载resource或url if (resource != null) { defaults.putAll(Resources.getResourceAsProperties(resource)); } else if (url != null) { defaults.putAll(Resources.getUrlAsProperties(url)); } //与configuration对象中的variables集合合并 Properties vars = configuration.getVariables(); if (vars != null) { defaults.putAll(vars); } //更新XPathParser和Configuration的variables字段 parser.setVariables(defaults); configuration.setVariables(defaults); } } private void environmentsElement(XNode context) throws Exception { if (context != null) { //未指定XMLConfigBuilder.environment 字段,则使用default属性指定的< environment> if (environment == null) { environment = context.getStringAttribute("default"); } //遍历子节点(即< environment > 节点) for (XNode child : context.getChildren()) { String id = child.getStringAttribute("id"); //与XMLConfigBuilder.environment匹配 if (isSpecifiedEnvironment(id)) { //创建TransactionFactory ,具体实现是先通过TypeAliasRegistry 解析别名之后,实例化 TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager")); //创建DataSourceFactory 和DataSource DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource")); DataSource dataSource = dsFactory.getDataSource(); //创建Environment, Environment 中封装了上面创建的TransactionFactory 对象 以及DataSource 对象。这里应用了建造者模式 Environment.Builder environmentBuilder = new Environment.Builder(id) .transactionFactory(txFactory) .dataSource(dataSource); //将Environment 对象记录到Configuration.environment 字段中 configuration.setEnvironment(environmentBuilder.build()); } } } } private void databaseIdProviderElement(XNode context) throws Exception { DatabaseIdProvider databaseIdProvider = null; if (context != null) { String type = context.getStringAttribute("type"); // awful patch to keep backward compatibility //为了保证兼容性,修改type 取值 if ("VENDOR".equals(type)) { type = "DB_VENDOR"; } Properties properties = context.getChildrenAsProperties(); //创建DatabaseidProvider 对象 databaseIdProvider = (DatabaseIdProvider) resolveClass(type).getDeclaredConstructor().newInstance(); //配置DatabaseidProvider ,完成初始化 databaseIdProvider.setProperties(properties); } Environment environment = configuration.getEnvironment(); if (environment != null && databaseIdProvider != null) { //通过前面确定的DataSource 获取database Id , 并记录到configuration.databaseid 字段中 String databaseId = databaseIdProvider.getDatabaseId(environment.getDataSource()); configuration.setDatabaseId(databaseId); } } private void mapperElement(XNode parent) throws Exception { if (parent != null) { //处理< mappers >的子节点 for (XNode child : parent.getChildren()) { //<package >子节点 if ("package".equals(child.getName())) { String mapperPackage = child.getStringAttribute("name"); //扫描指定的包,并向MapperRegistry 注册Mapper 接口 configuration.addMappers(mapperPackage); } else { //获取<mapper >节点的resource 、url 、class 属性,这三个属性互斥 String resource = child.getStringAttribute("resource"); String url = child.getStringAttribute("url"); String mapperClass = child.getStringAttribute("class"); //如果<mapper >节点指定了resource 或是url 属性,则创建XMLMapperBuilder 对象,并通过该对象解析resource 或是url 属性指定的Mapper 配置文件 if (resource != null && url == null && mapperClass == null) { ErrorContext.instance().resource(resource); InputStream inputStream = Resources.getResourceAsStream(resource); //创建XMLMapperBu 工lder 对象,解析映射配置文件 XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments()); mapperParser.parse(); } else if (resource == null && url != null && mapperClass == null) { ErrorContext.instance().resource(url); InputStream inputStream = Resources.getUrlAsStream(url); //创建XMLMapperBuilder 对象, 解析映射配置文件 XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments()); mapperParser.parse(); } else if (resource == null && url == null && mapperClass != null) { //如果<mapper >节点指定了class属性,则向MapperRegistry 注册该Mapper 接口 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 # ## XMLMapperBuilder ## /** * 解析映射配置文件 * @author Clinton Begin * @author Kazuki Shimizu */ public class XMLMapperBuilder extends BaseBuilder { public void parse() { //判断是否已经加载过该映射文件 if (!configuration.isResourceLoaded(resource)) { configurationElement(parser.evalNode("/mapper")); configuration.addLoadedResource(resource); //注册Mapper 接口 bindMapperForNamespace(); } //处理configurationElement ()方法中解析失败的< resultMap > 节点 parsePendingResultMaps(); //处理configurationElement ()方法中解析失败的< cache-ref >节点 parsePendingCacheRefs(); //处理configurationElement ()方法中解析失败的SQL 语句节点 parsePendingStatements(); } private void configurationElement(XNode context) { try { //获取<mapper > 节点的namespace 属性 String namespace = context.getStringAttribute("namespace"); if (namespace == null || namespace.isEmpty()) { throw new BuilderException("Mapper's namespace cannot be empty"); } //设置MapperBuilderAssistant的currentNamespace 字段,记录当前命名空间 builderAssistant.setCurrentNamespace(namespace); //解析< cache - ref > 节点 //多个namespace 共用同一个二级缓存,即同一个Cache 对象, 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 >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); } } private void cacheRefElement(XNode context) { if (context != null) { //将当前Mapper 配置文件的namespace 与被引用的Cache 所在的namespace 之间的对应关系,记录到Configuration.cacheRefMap 集合中 configuration.addCacheRef(builderAssistant.getCurrentNamespace(), context.getStringAttribute("namespace")); //创建CacheRefResolver 对象 CacheRefResolver cacheRefResolver = new CacheRefResolver(builderAssistant, context.getStringAttribute("namespace")); try { //解析Cache 引用,该过程主要是设置MapperBuilderAssistant 中的currentCache 和unresolvedCacheRef 字段 cacheRefResolver.resolveCacheRef(); } catch (IncompleteElementException e) { //如解析过程出现异常,则添加到Configuration.incompleteCacheRefs 集合, 稍后再解析 configuration.addIncompleteCacheRef(cacheRefResolver); } } } private void cacheElement(XNode context) { if (context != null) { //获取< cache >节点的type ),默认位是PERPETUAL String type = context.getStringAttribute("type", "PERPETUAL"); Class<? extends Cache> typeClass = typeAliasRegistry.resolveAlias(type); //获取< cache > 节点的eviction 属性,默认LRU String eviction = context.getStringAttribute("eviction", "LRU"); //解析eviction 属性指定的Cache 装饰器类型 Class<? extends Cache> evictionClass = typeAliasRegistry.resolveAlias(eviction); Long flushInterval = context.getLongAttribute("flushInterval"); Integer size = context.getIntAttribute("size"); boolean readWrite = !context.getBooleanAttribute("readOnly", false); boolean blocking = context.getBooleanAttribute("blocking", false); //获取< cache >节点下的子节点,将用于初始化二级缓存 Properties props = context.getChildrenAsProperties(); //通过MapperBuilderAssistant 创建Cache 对象,并添加到Configuration . caches 集合中保存 builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, blocking, props); } } private ResultMap resultMapElement(XNode resultMapNode, List<ResultMapping> additionalResultMappings, Class<?> enclosingType) { ErrorContext.instance().activity("processing " + resultMapNode.getValueBasedIdentifier()); //获取< resultMap >节点的type 属性,表示结果集集将被映射成type 指定类型的对象, String type = resultMapNode.getStringAttribute("type", resultMapNode.getStringAttribute("ofType", resultMapNode.getStringAttribute("resultType", resultMapNode.getStringAttribute("javaType")))); //解析type 类型 Class<?> typeClass = resolveClass(type); if (typeClass == null) { typeClass = inheritEnclosingType(resultMapNode, enclosingType); } Discriminator discriminator = null; //该集合用于记录解析的结果 List<ResultMapping> resultMappings = new ArrayList<>(additionalResultMappings); //处理< resultMap > 的子节点 List<XNode> resultChildren = resultMapNode.getChildren(); for (XNode resultChild : resultChildren) { if ("constructor".equals(resultChild.getName())) { //处理<constructor> 节点 processConstructorElement(resultChild, typeClass, resultMappings); } else if ("discriminator".equals(resultChild.getName())) { //处理<discriminator>节点 discriminator = processDiscriminatorElement(resultChild, typeClass, resultMappings); } else { // 处理< id>、<result>、<association>、<collection >等节点 List<ResultFlag> flags = new ArrayList<>(); if ("id".equals(resultChild.getName())) { // 如果是< id>节点,则向flags 集合中添加ResultFlag.ID flags.add(ResultFlag.ID); } // 创建ResultMapping 对象,并添加到resultMappings 集合中保存 resultMappings.add(buildResultMappingFromContext(resultChild, typeClass, flags)); } } //获取< resultMap >的id 属性,默认值会拼笨所有父节点的id 或value 或Property值 String id = resultMapNode.getStringAttribute("id", resultMapNode.getValueBasedIdentifier()); //获取< resultMap >节点的extends 属性,该属性指定了该< resultMap>节点的继承关系 String extend = resultMapNode.getStringAttribute("extends"); //读取< resultMap >节点的autoMapping 属性, 将该属性设置为true ,则启动自动映射功能 //即自动查找与列名同名的属性名,并调用setter 方法。而设置为false 后, 9)1] 需 //要在< resultMap > 节点内明确注明映射关系才会调用对应的setter 方法。 Boolean autoMapping = resultMapNode.getBooleanAttribute("autoMapping"); ResultMapResolver resultMapResolver = new ResultMapResolver(builderAssistant, id, typeClass, extend, discriminator, resultMappings, autoMapping); try { //创建ResultMap 对象,并添加到Configuration.resultMaps 集合中,该集合是StrictMap 类型 return resultMapResolver.resolve(); } catch (IncompleteElementException e) { configuration.addIncompleteResultMap(resultMapResolver); throw e; } } private ResultMapping buildResultMappingFromContext(XNode context, Class<?> resultType, List<ResultFlag> flags) { String property; if (flags.contains(ResultFlag.CONSTRUCTOR)) { property = context.getStringAttribute("name"); } else { 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.emptyList(), resultType)); String notNullColumn = context.getStringAttribute("notNullColumn"); String columnPrefix = context.getStringAttribute("columnPrefix"); String typeHandler = context.getStringAttribute("typeHandler"); String resultSet = context.getStringAttribute("resultSet"); String foreignColumn = context.getStringAttribute("foreignColumn"); boolean lazy = "lazy".equals(context.getStringAttribute("fetchType", configuration.isLazyLoadingEnabled() ? "lazy" : "eager")); //解析javaType 、typeHandler 和jdbcType Class<?> javaTypeClass = resolveClass(javaType); Class<? extends TypeHandler<?>> typeHandlerClass = resolveClass(typeHandler); JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType); //创建ResultMapping 对象 return builderAssistant.buildResultMapping(resultType, property, column, javaTypeClass, jdbcTypeEnum, nestedSelect, nestedResultMap, notNullColumn, columnPrefix, typeHandlerClass, flags, resultSet, foreignColumn, lazy); } private void processConstructorElement(XNode resultChild, Class<?> resultType, List<ResultMapping> resultMappings) { // 获取< constructor >节点的子节点 List<XNode> argChildren = resultChild.getChildren(); for (XNode argChild : argChildren) { List<ResultFlag> flags = new ArrayList<>(); //添加CONSTRUCTOR 标志 flags.add(ResultFlag.CONSTRUCTOR); if ("idArg".equals(argChild.getName())) { //对于<idArg>节点,添加ID标志 flags.add(ResultFlag.ID); } //创建ResultMapping 对象,并添加到resultMappings 集合中 resultMappings.add(buildResultMappingFromContext(argChild, resultType, flags)); } } private String processNestedResultMappings(XNode context, List<ResultMapping> resultMappings, Class<?> enclosingType) { // 只会处理< association >、< collection >和< case >三种节点 //指定了select 属性之后,不会生成嵌套的ResultMap 对象 if (Arrays.asList("association", "collection", "case").contains(context.getName()) && context.getStringAttribute("select") == null) { validateCollection(context, enclosingType); ResultMap resultMap = resultMapElement(context, resultMappings, enclosingType); return resultMap.getId(); } return null; } private Discriminator processDiscriminatorElement(XNode context, Class<?> resultType, List<ResultMapping> resultMappings) { String column = context.getStringAttribute("column"); String javaType = context.getStringAttribute("javaType"); String jdbcType = context.getStringAttribute("jdbcType"); String typeHandler = context.getStringAttribute("typeHandler"); Class<?> javaTypeClass = resolveClass(javaType); Class<? extends TypeHandler<?>> typeHandlerClass = resolveClass(typeHandler); JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType); //处理<discriminator >节点的子节点 Map<String, String> discriminatorMap = new HashMap<>(); for (XNode caseChild : context.getChildren()) { String value = caseChild.getStringAttribute("value"); //调用processNestedResultMappings ( ) 方法创建嵌套的ResultMap 对象 String resultMap = caseChild.getStringAttribute("resultMap", processNestedResultMappings(caseChild, resultMappings, resultType)); //记录该列值与对应选择的ResultMap 的Id discriminatorMap.put(value, resultMap); } //创建Discriminator 对象 return builderAssistant.buildDiscriminator(resultType, column, javaTypeClass, jdbcTypeEnum, typeHandlerClass, discriminatorMap); } private void sqlElement(List<XNode> list, String requiredDatabaseId) { //遥历< sql >节点 for (XNode context : list) { //获取databaseid 属性 String databaseId = context.getStringAttribute("databaseId"); //获取id 属性 String id = context.getStringAttribute("id"); //为id 添加命名空间 id = builderAssistant.applyCurrentNamespace(id, false); //检测< sql >的database Id 与当前Configuration 中记录的database Id 是否一致 if (databaseIdMatchesCurrent(id, databaseId, requiredDatabaseId)) { //记录到XMLMapperBuilder.sqlFragments ( Map<String , XNode >类型)中保存, // 在XMLMapperBuilder的构造函数中,可以看到该字段指向了Configuration.sqlFragments 集合 sqlFragments.put(id, context); } } } } ## MapperBuilderAssistant ## public class MapperBuilderAssistant extends BaseBuilder { public Cache useCacheRef(String namespace) { if (namespace == null) { throw new BuilderException("cache-ref element requires a namespace attribute."); } try { // 标识未成功解析Cache 引用 unresolvedCacheRef = true; // 获取namespace对应的Cache 对象 Cache cache = configuration.getCache(namespace); if (cache == null) { throw new IncompleteElementException("No cache for namespace '" + namespace + "' could be found."); } // 记录当前命名空间使用的Cache currentCache = cache; // 标识已成功解析Cache 引用 unresolvedCacheRef = false; return cache; } catch (IllegalArgumentException e) { throw new IncompleteElementException("No cache for namespace '" + namespace + "' could be found.", e); } } public Cache useNewCache(Class<? extends Cache> typeClass, Class<? extends Cache> evictionClass, Long flushInterval, Integer size, boolean readWrite, boolean blocking, Properties props) { Cache cache = new CacheBuilder(currentNamespace) .implementation(valueOrDefault(typeClass, PerpetualCache.class)) .addDecorator(valueOrDefault(evictionClass, LruCache.class)) .clearInterval(flushInterval) .size(size) .readWrite(readWrite) .blocking(blocking) .properties(props) .build(); //将Cache 对象添加到Configuration.caches 集合中保存,其中会将Cache 的id 作为key,Cache 对象本身作为value configuration.addCache(cache); //记录当前命名空间使用的cache 对象 currentCache = cache; return cache; } 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) { //解析< resultType >节点指定的property 属性的类型 Class<?> javaTypeClass = resolveResultJavaType(resultType, property, javaType); //获取typeHandler 指定的TypeHandler 对象,底层依赖于typeHandlerRegistry , TypeHandler<?> typeHandlerInstance = resolveTypeHandler(javaTypeClass, typeHandler); //解析column 属性值,当column 是” { propl=coll , prop2=col2 }” 形式时, 会解析成ResultMapping 对象集合, // column 的这种形式主要用于嵌套查询的参数传递, List<ResultMapping> composites; if ((nestedSelect == null || nestedSelect.isEmpty()) && (foreignColumn == null || foreignColumn.isEmpty())) { composites = Collections.emptyList(); } else { composites = parseCompositeColumnName(column); } return new ResultMapping.Builder(configuration, property, column, javaTypeClass) .jdbcType(jdbcType) .nestedQueryId(applyCurrentNamespace(nestedSelect, true)) .nestedResultMapId(applyCurrentNamespace(nestedResultMap, true)) .resultSet(resultSet) .typeHandler(typeHandlerInstance) .flags(flags == null ? new ArrayList<>() : flags) .composites(composites) .notNullColumns(parseMultipleColumnNames(notNullColumn)) .columnPrefix(columnPrefix) .foreignColumn(foreignColumn) .lazy(lazy) .build(); } public ResultMap addResultMap( String id, Class<?> type, String extend, Discriminator discriminator, List<ResultMapping> resultMappings, Boolean autoMapping) { // ResultMap 的完整id 足” namespace . id ” 的格式 id = applyCurrentNamespace(id, false); //获取被继承的ResultMap 的完整id ,也就是父ResultMap 对象的完整id extend = applyCurrentNamespace(extend, true); //针对extend 属性的处理 if (extend != null) { if (!configuration.hasResultMap(extend)) { throw new IncompleteElementException("Could not find a parent resultmap with id '" + extend + "'"); } //检测Configuration.resultMaps 集合中是否存在被继承的ResultMap 对象 //获取需要被继承的ResultMap 对象,也就是父ResultMap 对象 ResultMap resultMap = configuration.getResultMap(extend); //获取父ResultMap 对象中记录的ResultMapping 集合 List<ResultMapping> extendedResultMappings = new ArrayList<>(resultMap.getResultMappings()); //删除需要覆盖的ResultMapping 集合 extendedResultMappings.removeAll(resultMappings); // Remove parent constructor if this resultMap declares a constructor. // 如果当前< resultMap > 节点中定义了< constructor >节点,则不需要使用父ResultMap 中记录 // 的相应< constructor > 节点,则将其对应的ResultMapping 对象删除 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)); } //添加需要被继承下来的ResultMapping 对象集合 resultMappings.addAll(extendedResultMappings); } //创建ResultMap 对象, 并添加到Configuration.resultMaps 集合中保存 ResultMap resultMap = new ResultMap.Builder(configuration, id, type, resultMappings, autoMapping) .discriminator(discriminator) .build(); configuration.addResultMap(resultMap); return resultMap; } } ## CacheBuilder ## public class CacheBuilder { //Cache 对象的唯一标识, 一般情况下对应映射文件中的配置name space private final String id; // Cache 接口的真正实现类,默认位是前面介绍的PerpetualCache private Class<? extends Cache> implementation; // 装饰器集合,默认只包含LruCache . class private final List<Class<? extends Cache>> decorators; // Cache大小 private Integer size; // 清理时间周期 private Long clearInterval; // 是否可读写 private boolean readWrite; // 其他配置信息 private Properties properties; // 是否阻塞 private boolean blocking; public Cache build() { /*默认implementation:PerpetualCache 装饰器集合默认:LruCache*/ setDefaultImplementations(); //根据implementation 指定的类型, 通过反射获取参数为String 类型的构造方法,并通过该构造方法创建Cache 对象 Cache cache = newBaseCacheInstance(implementation, id); //初始化Cache 对象 setCacheProperties(cache); // issue #352, do not apply decorators to custom caches //检测cache 对象的类型,如果是PerpetualCache 类型,为其添加decorators 集合中的装饰器; // 如果是自定义类型的Cache 接口实现,则不添加decorators 集合中的装饰~ if (PerpetualCache.class.equals(cache.getClass())) { for (Class<? extends Cache> decorator : decorators) { //通过反射获取参数为Cache 类型的构造方法,并通过该构造方法创建装饰器 cache = newCacheDecoratorInstance(decorator, cache); // 配置cache对象的属性 setCacheProperties(cache); } //添加MyBatis中提供的标准装饰器 cache = setStandardDecorators(cache); } else if (!LoggingCache.class.isAssignableFrom(cache.getClass())) { //如果不是LoggingCache 的子类,则添加LoggingCache 装饰器 cache = new LoggingCache(cache); } return cache; } private Cache setStandardDecorators(Cache cache) { try { //创建cache 对象对应的MetaObject 对象 MetaObject metaCache = SystemMetaObject.forObject(cache); if (size != null && metaCache.hasSetter("size")) { metaCache.setValue("size", size); } //检测是否指定了clearinterval 字段 if (clearInterval != null) { //添加ScheduledCache 装饰器 cache = new ScheduledCache(cache); // 设置ScheduledCache 的clearInterval 字段 ((ScheduledCache) cache).setClearInterval(clearInterval); } //是否只读,对应添加SerializedCache装饰器 if (readWrite) { cache = new SerializedCache(cache); } //默认添加LoggingCache 和SynchronizedCache 两个装饰器 cache = new LoggingCache(cache); cache = new SynchronizedCache(cache); //是否阻塞,对应添加BlockingCache 装饰器 if (blocking) { cache = new BlockingCache(cache); } return cache; } catch (Exception e) { throw new CacheException("Error building standard cache decorators. Cause: " + e, e); } } private void setCacheProperties(Cache cache) { if (properties != null) { // cache 对应的创建MetaObject 对象 MetaObject metaCache = SystemMetaObject.forObject(cache); for (Map.Entry<Object, Object> entry : properties.entrySet()) { // 配置项的名称, Cache 对应的属性名称 String name = (String) entry.getKey(); // 配置项的值,Cache对应的属性佳 String value = (String) entry.getValue(); //检测cache 是否有该属性对应的setter 方法 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); } } } } //如果Cache类继承了InitializingObject 接口, 则调用其initialize () 方法继续自定义的初始化操作 if (InitializingObject.class.isAssignableFrom(cache.getClass())) { try { ((InitializingObject) cache).initialize(); } catch (Exception e) { throw new CacheException("Failed cache initialization for '" + cache.getId() + "' on '" + cache.getClass().getName() + "'", e); } } } } ## ResultMapping ## public class ResultMapping { //Configuration 对象 private Configuration configuration; //对应节点的property 属性,表示的是与该列进行映射的属性 private String property; //对应节点的column 属性,表示的是从数据库中得到的列名或是列名的别名 private String column; //对应节点的javaType 属性,表示的是一个JavaBean的完全限定名,或一个类型别名 private Class<?> javaType; //对应节点的JdbcType属性,表示的是进行映射的列的JDBC 类型 private JdbcType jdbcType; //对应节点的typeHandler 属性,表示的是类型处理器,它会覆盖默认的类型处理器 private TypeHandler<?> typeHandler; //对应节点的resultMap 属性,该属性通过id 引用了另一个< resultMap >节点定义,它负责将结果集中的一部 //分列映射成其他关联的结果对象。这样我们就可以通过j oin 方式进行关联查询,然后直接映射成多个对象, //并同时设置这些对象之间的组合关系 private String nestedResultMapId; //对应节点的select 属性,该属性通过id引用了另一个< select >节点定义,它会把指定的列的值传入 // select 属性指定的select 语句中作为参数进行查询。使用select 属性可能会导致N+l 问题 private String nestedQueryId; //对应节点的notNullColumn 属性拆分后的结果 private Set<String> notNullColumns; //对应节点的columnPrefix 属性 private String columnPrefix; //处理后的标志,标志共两个: id 和constructor private List<ResultFlag> flags; //对应节点的column ,属性拆分后生成的结果, composites.size () >0 会使column 为null private List<ResultMapping> composites; // 对应节点的resultSet 属性 private String resultSet; //对应节点的foreignColumn 属性 private String foreignColumn; //是否延迟加载,对应节点的fetchType 属性 private boolean lazy; } ## ResultMap ## /** * @author Clinton Begin * 每个<resultMap >节点都会被解析成一个ResultMap 对 * 象,其中每个节点所定义的映射关系,则使用ResultMapping 对象表示 */ public class ResultMap { private Configuration configuration; // < resultMap > 节点的id 属性 private String id; // <resultMap > 的type 属性 private Class<?> type; // 记录了除<discriminator > 节点之外的其他映射关系(即ResultMapping 对象集合) private List<ResultMapping> resultMappings; // 记录了映射关系中带有ID 标志的映射关系,例如< id > 节点和< constructor >节点的< idArg > 子节点 private List<ResultMapping> idResultMappings; // 记录了映射关系中带有Constructor 标志的映射关系,例如< constructor> 所有子元素 private List<ResultMapping> constructorResultMappings; // 记录了映射关系中不带有Constructor 标志的映射关系 private List<ResultMapping> propertyResultMappings; // 记录所有映射关系中涉及的column属性的集合 private Set<String> mappedColumns; // 记录所有映射关系中涉及的Property属性的集合 private Set<String> mappedProperties; //鉴别器对应< discriminator > 节点 private Discriminator discriminator; //是否含有嵌套的结果映射,如果某个映射关系中存在resultMap 属性,且不存在resultSet 属性,则为tr ue private boolean hasNestedResultMaps; //是否含有嵌套查询,如果某个属性映射存在select 属性,则为true private boolean hasNestedQueries; //是否开启自动映射 private Boolean autoMapping; } # 解析SQL语句 # ## SqlSource ## /** * Represents the content of a mapped statement read from an XML file or an annotation. * It creates the SQL that will be passed to the database out of the input parameter received from the user. *表示映射文件或注解中定义的元SQL语句,含有占位符 * @author Clinton Begin */ public interface SqlSource { // getBoundSql ()方法会根据映射文件或注解描述的SQL 语句,以及传入的参敛,返回可执行的SQL BoundSql getBoundSql(Object parameterObject); } ## MappedStatement ## /** * @author Clinton Begin * 表示映射配置文件中定义的SQL节点 */ public final class MappedStatement { // 节点中的id属性(包括命名空间前缀) private String resource; private Configuration configuration; private String id; private Integer fetchSize; private Integer timeout; private StatementType statementType; private ResultSetType resultSetType; // SqlSource对象,对应一条SQL 语句 private SqlSource sqlSource; private Cache cache; private ParameterMap parameterMap; private List<ResultMap> resultMaps; private boolean flushCacheRequired; private boolean useCache; private boolean resultOrdered; // SQL 的类型, INSERT 、UPDATE 、DELETE 、SELECT 或FLUSH private SqlCommandType sqlCommandType; } ## XMLStatementBuilder ## public class XMLStatementBuilder extends BaseBuilder { /** * 解析SQL 节点的入口函数 */ public void parseStatementNode() { //获取SQL节点的id以及databaseId属性,若其databaseid属性值与当前使用的数据库不匹 配,则不加载该SQL 节点; //若存在相同id 且databaseid 不为空的SQL 节点,则不再加载该SQL 节点 String id = context.getStringAttribute("id"); String databaseId = context.getStringAttribute("databaseId"); if (!databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) { return; } // 根据SQL 节点的名称决定其SqlCommandType String nodeName = context.getNode().getNodeName(); 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 //在解析SQL 语句之前,先处理其中的< inclu de > 节点 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); // Parse selectKey after includes and remove them. //解析SQL 节点中的< selectKey>子节 点 processSelectKeyNodes(id, parameterTypeClass, langDriver); // Parse the SQL (pre: <selectKey> and <include> were parsed and removed) //完成SQL 节点的解析 KeyGenerator keyGenerator; //获取< selectKey> 节点对应的SelectKeyGenerator的i d 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); 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"); //这里会检测SQL 节点中是否配置了< selectKey > 节点、SQL 节点的useGeneratedKeys 属性值、 // mybatis-config.xml 中全局的useGeneratedKeys 配置,以及是否为insert 语句,决定使用的 // KeyGenerator 接口实现。 //通过MapperBuilderAssistant创建MappedStatement 对象,并添加到 // Configuration. mappedStatements 集合中保存 builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType, fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass, resultSetTypeEnum, flushCache, useCache, resultOrdered, keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets); } private void processSelectKeyNodes(String id, Class<?> parameterTypeClass, LanguageDriver langDriver) { //获取全部的< selectKey> 节点 List<XNode> selectKeyNodes = context.evalNodes("selectKey"); //解析< selectKey >节点 if (configuration.getDatabaseId() != null) { parseSelectKeyNodes(id, selectKeyNodes, parameterTypeClass, langDriver, configuration.getDatabaseId()); } parseSelectKeyNodes(id, selectKeyNodes, parameterTypeClass, langDriver, null); //移除< selectKey >节点 removeSelectKeyNodes(selectKeyNodes); } private void parseSelectKeyNodes(String parentId, List<XNode> list, Class<?> parameterTypeClass, LanguageDriver langDriver, String skRequiredDatabaseId) { for (XNode nodeToHandle : list) { String id = parentId + SelectKeyGenerator.SELECT_KEY_SUFFIX; String databaseId = nodeToHandle.getStringAttribute("databaseId"); if (databaseIdMatchesCurrent(id, databaseId, skRequiredDatabaseId)) { parseSelectKeyNode(id, nodeToHandle, parameterTypeClass, langDriver, databaseId); } } } private void parseSelectKeyNode(String id, XNode nodeToHandle, Class<?> parameterTypeClass, LanguageDriver langDriver, String databaseId) { //获取< selectKey >节点的result Type 、statement Type 、keyProperty 等属性 String resultType = nodeToHandle.getStringAttribute("resultType"); Class<?> resultTypeClass = resolveClass(resultType); StatementType statementType = StatementType.valueOf(nodeToHandle.getStringAttribute("statementType", StatementType.PREPARED.toString())); String keyProperty = nodeToHandle.getStringAttribute("keyProperty"); String keyColumn = nodeToHandle.getStringAttribute("keyColumn"); boolean executeBefore = "BEFORE".equals(nodeToHandle.getStringAttribute("order", "AFTER")); // 设置一系列MappedStatement 对象需要的默认配置,例如, useCache 、fetchSize 等 // defaults boolean useCache = false; boolean resultOrdered = false; KeyGenerator keyGenerator = NoKeyGenerator.INSTANCE; Integer fetchSize = null; Integer timeout = null; boolean flushCache = false; String parameterMap = null; String resultMap = null; ResultSetType resultSetTypeEnum = null; //通过LanguageDriver.createSqlSource ()方法生成SqlSource SqlSource sqlSource = langDriver.createSqlSource(configuration, nodeToHandle, parameterTypeClass); // <selectKey > 节点中只能配置selectt吾句 SqlCommandType sqlCommandType = SqlCommandType.SELECT; //通过MapperBuilderAssistant 创建MappedStatement 对象,并添加到 // Configuration.mappedStatements 集合中保存,该集合为StrictMap<MappedStatement > 类型 builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType, fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass, resultSetTypeEnum, flushCache, useCache, resultOrdered, keyGenerator, keyProperty, keyColumn, databaseId, langDriver, null); id = builderAssistant.applyCurrentNamespace(id, false); MappedStatement keyStatement = configuration.getMappedStatement(id, false); //创建< selectKey > 节点对应的KeyGenerator ,添加到Configuration . keyGenerators 集合中 //保存, Configuration.keyGenerators 字段是StrictMap<KeyGenerator>类型的对象 configuration.addKeyGenerator(id, new SelectKeyGenerator(keyStatement, executeBefore)); } } public class XMLScriptBuilder extends BaseBuilder { public SqlSource parseScriptNode() { //首先判断当前的节点是不是有动态SQL ,动态SQL 会包括占位符或是动态SQL 的相关节点 MixedSqlNode rootSqlNode = parseDynamicTags(context); SqlSource sqlSource; //根据是否是动态SQL , 创建相应的SqlSource 对象 if (isDynamic) { sqlSource = new DynamicSqlSource(configuration, rootSqlNode); } else { sqlSource = new RawSqlSource(configuration, rootSqlNode, parameterType); } return sqlSource; } protected MixedSqlNode parseDynamicTags(XNode node) { //用于记录生成的SqlNode 集合 List<SqlNode> contents = new ArrayList<>(); //获取SelectKey 的所有子节点 NodeList children = node.getNode().getChildNodes(); for (int i = 0; i < children.getLength(); i++) { //创建XNode ,该过程会将能解析掉的” ${} ” 都解析掉 XNode child = node.newXNode(children.item(i)); if (child.getNode().getNodeType() == Node.CDATA_SECTION_NODE || child.getNode().getNodeType() == Node.TEXT_NODE) { String data = child.getStringBody(""); TextSqlNode textSqlNode = new TextSqlNode(data); //解析SQL 语句,如果含有未解析的”${}”占位符,则为动态SQL if (textSqlNode.isDynamic()) { contents.add(textSqlNode); // 标记为动态SQL 语句 isDynamic = true; } else { contents.add(new StaticTextSqlNode(data)); } } else if (child.getNode().getNodeType() == Node.ELEMENT_NODE) { // issue #628 //如果子节点是一个标签,那么一定是动态SQL ,并且根据不同的动态标签生成不同的NodeHandler String nodeName = child.getNode().getNodeName(); //根据标签名称获取对应 的NodeHandler 对象 NodeHandler handler = nodeHandlerMap.get(nodeName); if (handler == null) { throw new BuilderException("Unknown element <" + nodeName + "> in SQL statement."); } //处理动态SQL ,并将解析得到的SqlNode 对象放入contents 集合中保存 handler.handleNode(child, contents); isDynamic = true; } } // SqlNode 集合包装成一个MixedSqlNode return new MixedSqlNode(contents); } private class WhereHandler implements NodeHandler { public WhereHandler() { // Prevent Synthetic Access } @Override public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) { //调用parseDynamicTags ()方法,解析< where >节点的子节点 MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle); //创建WhereSqlNode ,并添加到targetContents 集合中保存 WhereSqlNode where = new WhereSqlNode(configuration, mixedSqlNode); targetContents.add(where); } } } # 绑定Mapper 接口 # public class XMLMapperBuilder extends BaseBuilder { /** * 映射配置文件与对应Mapper 接口的绑定 */ private void bindMapperForNamespace() { //获取映射配置文件的命名空间 String namespace = builderAssistant.getCurrentNamespace(); if (namespace != null) { Class<?> boundType = null; try { //解析命名空间对应的类型 boundType = Resources.classForName(namespace); } catch (ClassNotFoundException e) { // ignore, bound type is not required } // 是否已经加载了boundType 接口 if (boundType != null && !configuration.hasMapper(boundType)) { // Spring may not know the real resource name so we set a flag // to prevent loading again this resource from the mapper interface // look at MapperAnnotationBuilder#loadXmlResource // 追加namespace前缀,并添加到Configuration.loadedResources 集合中保存 configuration.addLoadedResource("namespace:" + namespace); //调用M apperRegistry .addM apper ()方法,注册boundType 接口 configuration.addMapper(boundType); } } } } public class MapperRegistry { public <T> void addMapper(Class<T> type) { //检测type 是否为接口 if (type.isInterface()) { //检测是否已经加载过该接口 if (hasMapper(type)) { throw new BindingException("Type " + type + " is already known to the MapperRegistry."); } boolean loadCompleted = false; try { //将Mapper 接口对应的Class 对象和MapperProxyFactory 对象添加到knownMappers 集合 knownMappers.put(type, new MapperProxyFactory<>(type)); // It's important that the type is added before the parser is run // otherwise the binding may automatically be attempted by the // mapper parser. If the type is already known, it won't try. //XML 解析和注解的处理 MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type); parser.parse(); loadCompleted = true; } finally { if (!loadCompleted) { knownMappers.remove(type); } } } } } public class MapperAnnotationBuilder { /** * 解析Mapper 接口中的注解信息 */ public void parse() { String resource = type.toString(); //检测是否已经加载过该接口 if (!configuration.isResourceLoaded(resource)) { //检测是否加载过对应的映射配置文件,如果未加载,则创建XMLMapperBuilder 对象解析对应的 映射文件 loadXmlResource(); configuration.addLoadedResource(resource); assistant.setCurrentNamespace(type.getName()); //解析@CacheNamespace i主解 parseCache(); //解析@CacheNamespaceRef 注解 parseCacheRef(); //遍历接口中定义的全部方法 for (Method method : type.getMethods()) { if (!canHaveStatement(method)) { continue; } if (getSqlCommandType(method) == SqlCommandType.SELECT && method.getAnnotation(ResultMap.class) == null) { parseResultMap(method); } try { parseStatement(method); } catch (IncompleteElementException e) { //如果解析过程出现IncompleteElementException异常,可能是引用了未解析的注解, //这里将出现异常的方法添加到Configuration.incompleteMethods 集合中暂存, //该集合是LinkedList< MethodResolver >类型 configuration.addIncompleteMethod(new MethodResolver(this, method)); } } } //遍历Configuration.incompleteMethods 集合中记录的为解析的方法,并重新进行解析 parsePendingMethods(); } } # 处理incomplete *集合 # public class XMLMapperBuilder extends BaseBuilder { public void parse() { //判断是否已经加载过该映射文件 if (!configuration.isResourceLoaded(resource)) { configurationElement(parser.evalNode("/mapper")); configuration.addLoadedResource(resource); //注册Mapper 接口 bindMapperForNamespace(); } //处理configurationElement ()方法中解析失败的< resultMap > 节点 parsePendingResultMaps(); //处理configurationElement ()方法中解析失败的< cache-ref >节点 parsePendingCacheRefs(); //处理configurationElement ()方法中解析失败的SQL 语句节点 parsePendingStatements(); } private void parsePendingStatements() { //获取Configuration . incompleteStatements 集合 Collection<XMLStatementBuilder> incompleteStatements = configuration.getIncompleteStatements(); synchronized (incompleteStatements) { //遍历incompleteStatements 集合 Iterator<XMLStatementBuilder> iter = incompleteStatements.iterator(); while (iter.hasNext()) { try { // 重新解析SQL 语句节点 iter.next().parseStatementNode(); // 移除XMLStatementBuilder 对象 iter.remove(); } catch (IncompleteElementException e) { //依然元法解析,则忽略该节点 // Statement is still missing a resource... } } } } } # SqlNode&SqlSource # ## OgnlCache ## public final class OgnlCache { private static final OgnlMemberAccess MEMBER_ACCESS = new OgnlMemberAccess(); private static final OgnlClassResolver CLASS_RESOLVER = new OgnlClassResolver(); //对解析后的OGNL 表达式进行缓存 private static final Map<String, Object> expressionCache = new ConcurrentHashMap<>(); private OgnlCache() { // Prevent Instantiation of Static Class } public static Object getValue(String expression, Object root) { try { //创建OgnlContext 对象, OgnlClassResolver 替代了OGNL 中原有的DefaultClassResolver, // 其主要功能是使用Resource工具类定位资源 Map context = Ognl.createDefaultContext(root, MEMBER_ACCESS, CLASS_RESOLVER, null); //使用OGNL 执行expression 表达式 return Ognl.getValue(parseExpression(expression), context, root); } catch (OgnlException e) { throw new BuilderException("Error evaluating expression '" + expression + "'. Cause: " + e, e); } } private static Object parseExpression(String expression) throws OgnlException { //查找缓存 Object node = expressionCache.get(expression); if (node == null) { // 解析表达式 node = Ognl.parseExpression(expression); // 将表达式的解析结采添加到缓存中 expressionCache.put(expression, node); } return node; } } ## DynamicContext ## /** * @author Clinton Begin * 记录解析动态SQL 语句之后产生的SQL 语句片段 */ public class DynamicContext { public static final String PARAMETER_OBJECT_KEY = "_parameter"; public static final String DATABASE_ID_KEY = "_databaseId"; static { OgnlRuntime.setPropertyAccessor(ContextMap.class, new ContextAccessor()); } //参数上下文 private final ContextMap bindings; //在SqlNode 解析动态SQL 时,会将解析后的SQL语句片段添加到该属性中保存,最终拼凑出一条完成的SQL 语句 private final StringJoiner sqlBuilder = new StringJoiner(" "); private int uniqueNumber = 0; public DynamicContext(Configuration configuration, Object parameterObject) { if (parameterObject != null && !(parameterObject instanceof Map)) { //对于非Map 类型的参数,会创建对应的MetaObject 对象,并封装成ContextMap 对象 MetaObject metaObject = configuration.newMetaObject(parameterObject); boolean existsTypeHandler = configuration.getTypeHandlerRegistry().hasTypeHandler(parameterObject.getClass()); bindings = new ContextMap(metaObject, existsTypeHandler); } else { bindings = new ContextMap(null, false); } bindings.put(PARAMETER_OBJECT_KEY, parameterObject); bindings.put(DATABASE_ID_KEY, configuration.getDatabaseId()); } // 追加SQL 片段 public void appendSql(String sql) { sqlBuilder.add(sql); } //获取解析后的、完整的SQL 语句 public String getSql() { return sqlBuilder.toString().trim(); } static class ContextMap extends HashMap<String, Object> { private static final long serialVersionUID = 2977601501966151582L; //将用户传入的参数封装成了MetaObject 对象 private final MetaObject parameterMetaObject; private final boolean fallbackParameterObject; public ContextMap(MetaObject parameterMetaObject, boolean fallbackParameterObject) { this.parameterMetaObject = parameterMetaObject; this.fallbackParameterObject = fallbackParameterObject; } @Override public Object get(Object key) { String strKey = (String) key; //如果ContextMap 中已经包含了该key ,则直接返回 if (super.containsKey(strKey)) { return super.get(strKey); } if (parameterMetaObject == null) { return null; } if (fallbackParameterObject && !parameterMetaObject.hasGetter(strKey)) { return parameterMetaObject.getOriginalObject(); } else { // issue #61 do not modify the context when reading //从运行时参数中查找对应属性 return parameterMetaObject.getValue(strKey); } } } } ## SqlNode ## public interface SqlNode { // apply ()是SqlNode 接口中定义的唯一方法,该方法会根据用户传入的实参,参数解析该SqlNode 所 //记录的动态SQL 节点,并调用DynamicContext.appendSql ()方法将解析后的SQL 片段追加到 //DynamicContext.sqlBuilder 中保存 //当SQL 节点下的所有SqlNode 完成解析后,我们就可以从DynamicContext中获取一条动态生成的、 //完整的SQL 语句 boolean apply(DynamicContext context); } ## TextSqlNode ## /** * @author Clinton Begin * 表示的是包含“${}”占位符的动态SQL 节点 */ public class TextSqlNode implements SqlNode { @Override public boolean apply(DynamicContext context) { //使用Ge nericTokenParser解析“${}”占位符,并直接替换成用户给定的实际参数值 GenericTokenParser parser = createParser(new BindingTokenParser(context, injectionFilter)); // 将解析后的SQL 片段添加到DynamicContext 中 context.appendSql(parser.parse(text)); return true; } private GenericTokenParser createParser(TokenHandler handler) { //解析的是”♀{}”占位符 return new GenericTokenParser("${", "}", handler); } private static class BindingTokenParser implements TokenHandler { @Override public String handleToken(String content) { //获取用户提供的实参 Object parameter = context.getBindings().get("_parameter"); if (parameter == null) { context.getBindings().put("value", null); } else if (SimpleTypeRegistry.isSimpleType(parameter.getClass())) { context.getBindings().put("value", parameter); } //通过OGNL 解析content 的值 Object value = OgnlCache.getValue(content, context.getBindings()); String srtValue = value == null ? "" : String.valueOf(value); // issue #274 return "" instead of "null" // 检测合法性 checkInjection(srtValue); return srtValue; } } } ## IfSqlNode ## /** * @author Clinton Begin * 对应的动态SQL节点是<If>节点 */ public class IfSqlNode implements SqlNode { // ExpressionEvaluator 对象用于解析< if >节点的test 表达式的值 private final ExpressionEvaluator evaluator; // 记录了< if >节点中的test 表达式 private final String test; // 记录了< if >节点的子节点 private final SqlNode contents; public IfSqlNode(SqlNode contents, String test) { this.test = test; this.contents = contents; this.evaluator = new ExpressionEvaluator(); } @Override public boolean apply(DynamicContext context) { //检测test 属性中记录的表达式 if (evaluator.evaluateBoolean(test, context.getBindings())) { //test 表达式为true, 则执行子节点的apply ()方法 contents.apply(context); return true; } return false; } } public boolean evaluateBoolean(String expression, Object parameterObject) { //首先通过OGNL 解析表达式的值 Object value = OgnlCache.getValue(expression, parameterObject); //处理Boolean 类型 if (value instanceof Boolean) { return (Boolean) value; } //处理数字类型 if (value instanceof Number) { return new BigDecimal(String.valueOf(value)).compareTo(BigDecimal.ZERO) != 0; } return value != null; } ## TrimSqlNode ## /** * @author Clinton Begin * 根据子节点的解析结果,添加或删除相应的前缀或后缀 */ public class TrimSqlNode implements SqlNode { //该<trim> 节点的子节点 private final SqlNode contents; //记录了前缀字符串(为<trim>节点包袤的SQL 语句添加的前缀) private final String prefix; //记录了后缀字符串(为<trim>节点包袤的SQL 语句添加的后缀) private final String suffix; //如果< trim >节点包袤的SQL 语句是空语句(经常出现在if 判断为否的情况下),删除指定的前缀,如where private final List<String> prefixesToOverride; //如果< trim> 包袤的SQL 语句是空语句(经常出现在if 判断为否的情况下),删除指定的后缀,如逗号 private final List<String> suffixesToOverride; private final Configuration configuration; @Override public boolean apply(DynamicContext context) { //创建FilteredDynamicContext 对象,其中封装了DynamicContext FilteredDynamicContext filteredDynamicContext = new FilteredDynamicContext(context); //调用子节点的apply ()方法进行解析 boolean result = contents.apply(filteredDynamicContext); //使用FilteredDynamicContext.applyAll ()方法处理前级和后缀 filteredDynamicContext.applyAll(); return result; } /** * prefixesToOverride和suffixesToOverride解析 * * 初始化prefixesToOverride 和suffixesToOverride * @param overrides * @return */ private static List<String> parseOverrides(String overrides) { if (overrides != null) { //按照” | ”进行分割 final StringTokenizer parser = new StringTokenizer(overrides, "|", false); final List<String> list = new ArrayList<>(parser.countTokens()); //转换为大写,并添加到集合中 while (parser.hasMoreTokens()) { list.add(parser.nextToken().toUpperCase(Locale.ENGLISH)); } return list; } return Collections.emptyList(); } private class FilteredDynamicContext extends DynamicContext { //底层封装的DynamicContext 对象 private DynamicContext delegate; //是否已经处理过前级和后缀,初始位都为false private boolean prefixApplied; private boolean suffixApplied; //用于记录子节点解析后的结果,FilteredDynamicContext. appendSql()方法会向该字段添加解析结果, //而不是调用delegate.appendSql ()方法 private StringBuilder sqlBuffer; public FilteredDynamicContext(DynamicContext delegate) { super(configuration, null); this.delegate = delegate; this.prefixApplied = false; this.suffixApplied = false; this.sqlBuffer = new StringBuilder(); } public void applyAll() { //获取子节点解析后的结采,并全部转换为大写 sqlBuffer = new StringBuilder(sqlBuffer.toString().trim()); String trimmedUppercaseSql = sqlBuffer.toString().toUpperCase(Locale.ENGLISH); if (trimmedUppercaseSql.length() > 0) { // 处理前缀 applyPrefix(sqlBuffer, trimmedUppercaseSql); // 处理后级 applySuffix(sqlBuffer, trimmedUppercaseSql); } // 将解析后的结果添加到delegate 中 delegate.appendSql(sqlBuffer.toString()); } private void applyPrefix(StringBuilder sql, String trimmedUppercaseSql) { //检测是否已经处理过前缀 if (!prefixApplied) { // 标记已处理过前缀 prefixApplied = true; if (prefixesToOverride != null) { // 边历prefixesToOverride 集合 for (String toRemove : prefixesToOverride) { if (trimmedUppercaseSql.startsWith(toRemove)) { //如果以prefixesToOverride 中某项开头,则将该项从SQL 语句开头删除掉 sql.delete(0, toRemove.trim().length()); break; } } } //添加p refix 前缀 if (prefix != null) { sql.insert(0, " "); sql.insert(0, prefix); } } } }} ## ForEachSqlNode ## public class ForEachSqlNode implements SqlNode { public static final String ITEM_PREFIX = "__frch_"; private final ExpressionEvaluator evaluator; // 迭代的集合表达式 private final String collectionExpression; //记录了该ForeachSqlNode 节点的子节点 private final SqlNode contents; // 在循环开始前要添加的字符串 private final String open; // 在循环结束后要添加的字符串 private final String close; // 循环过程中,每项之间的分隔符 private final String separator; // index 是当前迭代的次数, item 的值是本次选代的元素。若迭代集合是Map,则index 是键, item 是值 private final String item; private final String index; // 配置对象 private final Configuration configuration; @Override public boolean apply(DynamicContext context) { //获取参数信息 Map<String, Object> bindings = context.getBindings(); //解析集合表达式,获取对应的实际参数。 final Iterable<?> iterable = evaluator.evaluateIterable(collectionExpression, bindings); if (!iterable.iterator().hasNext()) { return true; } boolean first = true; //在循环开始之前,添加open 字段指定的字符串。 applyOpen(context); int i = 0; for (Object o : iterable) { DynamicContext oldContext = context; //根据遍历的位置和是否指定分隔符。用PrefixedContext封装 DynamicContext 。 if (first || separator == null) { // 如果集合的第一项,则将PrefixedContext.prefix 初始化为空字符串 context = new PrefixedContext(context, ""); } else { //如果指定了分隔符,则PrefixedContext.prefix初始化为指定分隔符 context = new PrefixedContext(context, separator); } //uniqueNumber从0 开始,每次递增l用于转换生成新的“#{}”占位符名称 int uniqueNumber = context.getUniqueNumber(); // Issue #709 //如果集合是Map 类型,将集合中key 和 value 添加到DynamicContext.bindings 集合中保存 if (o instanceof Map.Entry) { @SuppressWarnings("unchecked") Map.Entry<Object, Object> mapEntry = (Map.Entry<Object, Object>) o; //将index 添加到DynamicContext.bindings 集合中,供后续解析 使用, applyIndex(context, mapEntry.getKey(), uniqueNumber); //将item 添加到DynamicContext.bindings 集合中,供后续解析使用, applyItem(context, mapEntry.getValue(), uniqueNumber); } else { applyIndex(context, i, uniqueNumber); applyItem(context, o, uniqueNumber); } //转换子节点中的“#{}”占位符, contents.apply(new FilteredDynamicContext(configuration, context, index, item, uniqueNumber)); if (first) { first = !((PrefixedContext) context).isPrefixApplied(); } //还原成原来的context context = oldContext; i++; } //添加close 指定的字符串 applyClose(context); context.getBindings().remove(item); context.getBindings().remove(index); return true; } private void applyIndex(DynamicContext context, Object o, int i) { if (index != null) { //key为index, value是集合元素 context.bind(index, o); //为index 添加前级和后缀形成新的key context.bind(itemizeItem(index, i), o); } } //添加” frch ” 前级和i 后缀 private static String itemizeItem(String item, int i) { return ITEM_PREFIX + item + "_" + i; } //负责处理“#{}”占位符 private static class FilteredDynamicContext extends DynamicContext { private final DynamicContext delegate; //对应集合项在集合中的索引位置 private final int index; //对应集合项的index private final String itemIndex; //对应集合项的item private final String item; @Override public void appendSql(String sql) { //创建GenericTokenParser 解析器 GenericTokenParser parser = new GenericTokenParser("#{", "}", content -> { //对item 进行处理 String newContent = content.replaceFirst("^\\s*" + item + "(?![^.,:\\s])", itemizeItem(item, index)); if (itemIndex != null && newContent.equals(content)) { //对itemindex 进行处理 newContent = content.replaceFirst("^\\s*" + itemIndex + "(?![^.,:\\s])", itemizeItem(itemIndex, index)); } return "#{" + newContent + "}"; }); //将解析后的SQL 语句片段追加到del egate 中保存 delegate.appendSql(parser.parse(sql)); } } private class PrefixedContext extends DynamicContext { private final DynamicContext delegate; //指定的前缀 private final String prefix; //是否已经处理过前缀 private boolean prefixApplied; @Override public void appendSql(String sql) { //判断是否需要追加前缀 if (!prefixApplied && sql != null && sql.trim().length() > 0) { //追加前缀 delegate.appendSql(prefix); //表示已经处理过前缀 prefixApplied = true; } //追加sql 片段 delegate.appendSql(sql); } } ## ChooseSqlNode ## public class ChooseSqlNode implements SqlNode { // <otherwise >节点对应的SqlNode private final SqlNode defaultSqlNode; // <when >节点对应的IfSqlNode 集合 private final List<SqlNode> ifSqlNodes; @Override public boolean apply(DynamicContext context) { //遍历ifSqlNodes 集合并调用其中SqlNode 对象的apply ()方法 for (SqlNode sqlNode : ifSqlNodes) { if (sqlNode.apply(context)) { return true; } } //调用defaultSqlNode.apply()方法 if (defaultSqlNode != null) { defaultSqlNode.apply(context); return true; } return false; } } ## VarDeclSqlNode ## /** * @author Frank D. Martinez [mnesarco] * 表示的是动态SQL 语句中的<bind >节点, 该节点可以从OGNL表达式中创建一个变量并将其记录到上下文中 */ public class VarDeclSqlNode implements SqlNode { private final String name; private final String expression; @Override public boolean apply(DynamicContext context) { // 解析OGNL 表达式的值 final Object value = OgnlCache.getValue(expression, context.getBindings()); // 将name 和表达式的值存入DynamicContext.bindings 集合中 context.bind(name, value); return true; } } # 解析成BoundSql # ## SqlSourceBuilder ## /** * @author Clinton Begin * 解析SQL 语句中的“#{}”占位符中定义的属性,格式类似于#{_frc_item_ 0, javaType= int, jdbcType=NUMERIC,typeHandler=MyTypeHandler }, * 另一方面是将SQL 语句中的"#{}"占位符替换成“? ” 占位符。 */ public class SqlSourceBuilder extends BaseBuilder { /** * @param originalSql 经过SqlNode.apply ()方法处理之后的SQL 语句 * @param parameterType 用户传入的实参类型 * @param additionalParameters 记录形参与实参的对应关系,其实就是经过SqlNode . apply ()方法处理后的 * @return */ public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) { //创建ParameterMappingTokenHandler对象,它是解析” #{} ”占位符中的参数属性以及替换占位符 的核心 ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType, additionalParameters); //使用GenericTokenParser 与ParameterMappingTokenHandler 配合解析” #{} ”占位符 GenericTokenParser parser = new GenericTokenParser("#{", "}", handler); String sql = parser.parse(originalSql); // 创建StaticSqlSource,其中封装了占位符被替换成” ? ”的SQL 语句以及参数对应的ParameterMapping 集合 return new StaticSqlSource(configuration, sql, handler.getParameterMappings()); } private static class ParameterMappingTokenHandler extends BaseBuilder implements TokenHandler { // 用于记录解析得到的ParameterMapping 集合 private List<ParameterMapping> parameterMappings = new ArrayList<>(); // 参数类型 private Class<?> parameterType; // DynamicContext.bindings 集合对应的MetaObject 对象 private MetaObject metaParameters; @Override public String handleToken(String content) { //创建一个ParameterMapping 对象,并添加到parameterMappings 集合中保存 parameterMappings.add(buildParameterMapping(content)); //返回问号占位符 return "?"; } /** * 解析参数属性 * @param content * @return */ private ParameterMapping buildParameterMapping(String content) { /* 解析参数的属性并形成Map 。 例如#{_frc_item_0 , javaType=int, jdbcType=NUMERIC, typehandler=MyTypeHandler }这个占位符,它就会被解析成如下Map: { ” property ”- 〉” _ frch_item_0” ” javaType ” - > ” int ” ” jdbcType” - > ” NUMERIC ” ” typeHandler " - > ” MyTypeHandler ”}*/ Map<String, String> propertiesMap = parseParameterMapping(content); // 获取参数名称 String property = propertiesMap.get("property"); Class<?> propertyType; //确定参数的javaType 属性 if (metaParameters.hasGetter(property)) { // issue #448 get type from additional params propertyType = metaParameters.getGetterType(property); } else if (typeHandlerRegistry.hasTypeHandler(parameterType)) { propertyType = parameterType; } else if (JdbcType.CURSOR.name().equals(propertiesMap.get("jdbcType"))) { propertyType = java.sql.ResultSet.class; } else if (property == null || Map.class.isAssignableFrom(parameterType)) { propertyType = Object.class; } else { MetaClass metaClass = MetaClass.forClass(parameterType, configuration.getReflectorFactory()); if (metaClass.hasGetter(property)) { propertyType = metaClass.getGetterType(property); } else { propertyType = Object.class; } } //创建ParameterMapping 的建造者,并设置ParameterMapping 相关配置 ParameterMapping.Builder builder = new ParameterMapping.Builder(configuration, property, propertyType); Class<?> javaType = propertyType; String typeHandlerAlias = null; for (Map.Entry<String, String> entry : propertiesMap.entrySet()) { String name = entry.getKey(); String value = entry.getValue(); if ("javaType".equals(name)) { javaType = resolveClass(value); builder.javaType(javaType); } else if ("jdbcType".equals(name)) { builder.jdbcType(resolveJdbcType(value)); } else if ("mode".equals(name)) { builder.mode(resolveParameterMode(value)); } else if ("numericScale".equals(name)) { builder.numericScale(Integer.valueOf(value)); } else if ("resultMap".equals(name)) { builder.resultMapId(value); } else if ("typeHandler".equals(name)) { typeHandlerAlias = value; } else if ("jdbcTypeName".equals(name)) { builder.jdbcTypeName(value); } else if ("property".equals(name)) { // Do Nothing } else if ("expression".equals(name)) { throw new BuilderException("Expression based parameters are not supported yet"); } else { throw new BuilderException("An invalid property '" + name + "' was found in mapping #{" + content + "}. Valid properties are " + PARAMETER_PROPERTIES); } } //获取TypeHandler 对象 if (typeHandlerAlias != null) { builder.typeHandler(resolveTypeHandler(javaType, typeHandlerAlias)); } // 创建ParameterMapping 对象,注意,如果没有指定TypeHandler, 则会在这里的build ()方法中,根 // 据javaType和jdbcType 从TypeHandlerRegistry 中获取对应的TypeHandler 对象 return builder.build(); } } ## ParameterMapping ## public class ParameterMapping { private Configuration configuration; // 传入进来的参数name private String property; // 输入参数还是输出参数 private ParameterMode mode; // 参数的Java 类型 private Class<?> javaType = Object.class; // 参数的JDBC 类型 private JdbcType jdbcType; // 浮点参数的精度 private Integer numericScale; // 参数对应的Type Handler 对象 private TypeHandler<?> typeHandler; // 参数对应的ResultMap 的Id private String resultMapId; // 参数的j dbcTypeName 属性 private String jdbcTypeName; // 目前还不支持该属性 private String expression; } ## BoundSql ## public class BoundSql { //该字段中记录了SQL 语句,该SQL 语句中可能含有”?”占位符 private final String sql; // SQL 中的参数属性集合, ParameterMapping 的集合 private final List<ParameterMapping> parameterMappings; //客户端执行SQL 时传入的实际参数 private final Object parameterObject; //空的H ashMap 集合,之后会复制DynamicContext.bindings 集合中的内容 private final Map<String, Object> additionalParameters; // additionalParameters 集合对反的MetaObject对象 private final MetaObject metaParameters; } # SqlSource # ## DynamicSqlSource ## /** * @author Clinton Begin * 封装的SQL语句还需要进行一系列解析,才会最终形成数据库可执行的SQL 语句。 * 负责处理动态SQL语句, * 解析时机是在实际执行SQL 语句之前, */ public class DynamicSqlSource implements SqlSource { private final Configuration configuration; private final SqlNode rootSqlNode; public DynamicSqlSource(Configuration configuration, SqlNode rootSqlNode) { this.configuration = configuration; this.rootSqlNode = rootSqlNode; } @Override public BoundSql getBoundSql(Object parameterObject) { // 创建DynamicContext 对象, parameterObject 是用户传入的实参 DynamicContext context = new DynamicContext(configuration, parameterObject); //通过调用rootSqlNode.apply ()方法调用整个树形结构中全部SqlNode. apply ()方法,读者可以 // 体会一下组合设计模式的好处。每个SqlNode 的apply ()方法都将解析得到的SQL 语句片段追加到 // context 中, 最终通过context.getSql()得到完整的SQL 语句 rootSqlNode.apply(context); //创建SqlSourceBuilder ,解析参数属性,并将SQL 语句中的”#{ ) ” 占位符替换成” ? ” 占位符 SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration); Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass(); SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings()); //创建BoundSql 对象,并将DynamicContext.bindings 中的参数信息复制到其additionalParameters 集合中保存 BoundSql boundSql = sqlSource.getBoundSql(parameterObject); context.getBindings().forEach(boundSql::setAdditionalParameter); return boundSql; } } ## RawSqlSource ## /** * Static SqlSource. It is faster than {@link DynamicSqlSource} because mappings are * calculated during startup. * 负责处理静态SQL语句 * 解析时机是在MyBatis初始化时完成SQL 语句的解析 * @since 3.2.0 * @author Eduardo Macarron */ public class RawSqlSource implements SqlSource { // StaticSqlSource 对象 private final SqlSource sqlSource; public RawSqlSource(Configuration configuration, SqlNode rootSqlNode, Class<?> parameterType) { //调用getSql ()方法,完成SQL 语句的拼接和初步解析 this(configuration, getSql(configuration, rootSqlNode), parameterType); } public RawSqlSource(Configuration configuration, String sql, Class<?> parameterType) { //通过SqlSourceBuilder 完成占住符的解析和替换操作 SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration); Class<?> clazz = parameterType == null ? Object.class : parameterType; sqlSource = sqlSourceParser.parse(sql, clazz, new HashMap<>()); } private static String getSql(Configuration configuration, SqlNode rootSqlNode) { DynamicContext context = new DynamicContext(configuration, null); rootSqlNode.apply(context); return context.getSql(); } @Override public BoundSql getBoundSql(Object parameterObject) { return sqlSource.getBoundSql(parameterObject); } } # ResultSetHandler # ## ResultSetHandler ## /** * @author Clinton Begin * 负责映射select 语句查询得到的结果集, * 处理存储过程执行后的输出参数。 */ public interface ResultSetHandler { //处理结果集,生成相应的结果对象集合 <E> List<E> handleResultSets(Statement stmt) throws SQLException; //处理结果集,返回相应的游标对象 <E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException; //处理存储过程的输出参数 void handleOutputParameters(CallableStatement cs) throws SQLException; } ## DefaultResultSetHandler ## public class DefaultResultSetHandler implements ResultSetHandler { // 用户指定用于处理结果集的ResultHandler 对象 private final ResultHandler<?> resultHandler; /** * 处理Statement 、PreparedStatement 产生的结果集,还可以处理 * Callab leStatement 调用存储过程产生的多结果集。 * @param stmt * @return * @throws SQLException */ @Override public List<Object> handleResultSets(Statement stmt) throws SQLException { ErrorContext.instance().activity("handling results").object(mappedStatement.getId()); //保存映射结果集得到的结果对象 final List<Object> multipleResults = new ArrayList<>(); int resultSetCount = 0; // 获取第一个ResultSet 对象,可能存在多个ResultSet ,这里只获取第一个ResultSet ResultSetWrapper rsw = getFirstResultSet(stmt); List<ResultMap> resultMaps = mappedStatement.getResultMaps(); int resultMapCount = resultMaps.size(); validateResultMapsCount(rsw, resultMapCount); //结果集不为空,则resultMaps 集合不能为空, //遍历resultMaps 集合 while (rsw != null && resultMapCount > resultSetCount) { //获取该结果集对应的ResultMap 对象 ResultMap resultMap = resultMaps.get(resultSetCount); //根据ResultMap 中定义的映射规则对ResultSet 进行映射, 并将映射的结果对象添加到 multipleResults 集合中保存 //将未解析的结果集保存nextResultMaps暂存 handleResultSet(rsw, resultMap, multipleResults, null); //获取下一个结果集 rsw = getNextResultSet(stmt); //清空nestedResultObjects 集合 cleanUpAfterHandlingResultSet(); // 递增resultSetCount resultSetCount++; } //获取MappedStatement.resultSets属性。该属性仅对多结果集的情况适用,该属性将列出语句执 //行后返回的结果集,并给每个结果集一个名称,名称是逗号分隔的 String[] resultSets = mappedStatement.getResultSets(); if (resultSets != null) { while (rsw != null && resultSetCount < resultSets.length) { //根据resultSet 的名称,获取未处理的ResultMapping ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]); if (parentMapping != null) { String nestedResultMapId = parentMapping.getNestedResultMapId(); ResultMap resultMap = configuration.getResultMap(nestedResultMapId); //根据ResultMap 对象映射结果集 handleResultSet(rsw, resultMap, null, parentMapping); } // 获取下一个结果集 rsw = getNextResultSet(stmt); // 清空nestedResultObjects 集合 cleanUpAfterHandlingResultSet(); // 递增resultSetCount resultSetCount++; } } return collapseSingleResultList(multipleResults); } private ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException { // 获取ResultSet 对象 ResultSet rs = stmt.getResultSet(); while (rs == null) { // move forward to get the first resultset in case the driver // doesn't return the resultset as the first result (HSQLDB 2.1) // 检测是否还有待处理的ResultSet if (stmt.getMoreResults()) { rs = stmt.getResultSet(); } else { // 没有待处理的ResultSet if (stmt.getUpdateCount() == -1) { // no more results. Must be no resultset break; } } } //将结果集封装成ResultSetWrapper 对象 return rs != null ? new ResultSetWrapper(rs, configuration) : null; } private ResultSetWrapper getNextResultSet(Statement stmt) { // Making this method tolerant of bad JDBC drivers try { //检测JDBC 是否支持多结果集 if (stmt.getConnection().getMetaData().supportsMultipleResultSets()) { // Crazy Standard JDBC way of determining if there are more results //检测是否还有待处理的结果集, 若存在, 则封装成ResultSetWrapper 对象并返回 if (!(!stmt.getMoreResults() && stmt.getUpdateCount() == -1)) { ResultSet rs = stmt.getResultSet(); if (rs == null) { return getNextResultSet(stmt); } else { return new ResultSetWrapper(rs, configuration); } } } } catch (Exception e) { // Intentionally ignored. } return null; } private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException { try { if (parentMapping != null) { //处理多结果集中的嵌套映射 handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping); } else { if (resultHandler == null) { //如果用户未指定处理映射结果对象的ResultHandler 对象,则使用DefaultResultHandler 作为默认的ResultHandler 对象 DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory); //对ResultSet 进行映射,并将映射得到的结果对象添加到DefaultResultHandler 对 象中暂存 handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null); //将DefaultResultHandler 中保存的结果对象添加到multipleResults 集合中 multipleResults.add(defaultResultHandler.getResultList()); } else { //使用用户指定的ResultHandler 对象处理结果对象 handleRowValues(rsw, resultMap, resultHandler, rowBounds, null); } } } finally { // 调用ResultSet.close ()方法关闭结果集 // issue #228 (close resultsets) closeResultSet(rsw.getResultSet()); } } public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException { //针对存在嵌套ResultMap 的情况 if (resultMap.hasNestedResultMaps()) { //检测是否允许在嵌套映射中使用RowBound (略) ensureNoRowBounds(); //检测是否允许在嵌套映射中使用用户自定义的ResultHandler (略) checkResultHandler(); handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping); } else { //针对不含嵌套映射的简单映射的处理 handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping); } } private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException { //默认上下文对象 DefaultResultContext<Object> resultContext = new DefaultResultContext<>(); ResultSet resultSet = rsw.getResultSet(); //步骤1 :根据RowBounds 中的off set 定位到指定的记录 skipRows(resultSet, rowBounds); //步骤2 :检测已经处理的行数是否已经达到上限( RowBounds.limit )以及ResultSet 中是否还有可处理的记录 while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) { //步骤3 :根据该行记录以及Result Map.discriminator ,决定映射使用的ResultMap ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null); //步骤4 :根据最终确定的ResultMap对ResultSet 中的该行记录进行映射,得到映射后的结果对象 Object rowValue = getRowValue(rsw, discriminatedResultMap, null); //步骤5 :将映射创建的结果对象添加到ResultHandler.resultList 中保存 storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet); } } private void storeObject(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue, ResultMapping parentMapping, ResultSet rs) throws SQLException { if (parentMapping != null) { //嵌套查询或嵌套映射,将结果对象保存到父对象对应的属性中 linkToParents(rs, parentMapping, rowValue); } else { //普通映射,将结果对象保存到ResultHandler中 callResultHandler(resultHandler, resultContext, rowValue); } } @SuppressWarnings("unchecked" /* because ResultHandler<?> is always ResultHandler<Object>*/) private void callResultHandler(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue) { //递增DefaultResultContext.resultCount ,该值用于检测处理的记录行数是否已经达到 //上限(在RowBounds.limit 字段中记录了该上限)。之后将结果对象保存到DefaultResultContext.resultObject字段中 resultContext.nextResultObject(rowValue); //将结果对象添加到ResultHandler.resultList 中保存 ((ResultHandler<Object>) resultHandler).handleResult(resultContext); } private boolean shouldProcessMoreRows(ResultContext<?> context, RowBounds rowBounds) { return //检测DefaultResultContext.stopped 字段, !context.isStopped() && // 检测映射行数是否达 到了RowBounds.limit的限制 context.getResultCount() < rowBounds.getLimit(); } private void skipRows(ResultSet rs, RowBounds rowBounds) throws SQLException { //根据ResultSet 的类型进行定位 if (rs.getType() != ResultSet.TYPE_FORWARD_ONLY) { if (rowBounds.getOffset() != RowBounds.NO_ROW_OFFSET) { //直接定位到offset 指定的记录 rs.absolute(rowBounds.getOffset()); } } else { // 通过多次调用ResultSet.next ()方法移动到指定的记录 for (int i = 0; i < rowBounds.getOffset(); i++) { if (!rs.next()) { break; } } } } private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException { final ResultLoaderMap lazyLoader = new ResultLoaderMap(); //创建映射后的结果对象。该结果对象的类型由< resultMap >节点的type 属性指定 Object rowValue = createResultObject(rsw, resultMap, lazyLoader, columnPrefix); if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) { //创建上述结果对象相应的MetaObject对象 final MetaObject metaObject = configuration.newMetaObject(rowValue); // 成功映射任意属性,则foundValues 为true ;否则foundValues 为false boolean foundValues = this.useConstructorMappings; // 判断是否开启了自动映射功能 if (shouldApplyAutomaticMappings(resultMap, false)) { //自动映射ResultMap 中未明确映射的列。 foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues; } // 映射ResultMap 中明确映射列, foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues; foundValues = lazyLoader.size() > 0 || foundValues; //如果没有成功映射任何属性,则根据mybatis - config.xml 中的<returnInstanceForEmptyRow >配置决定返回空的结果对象还是返回null rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null; } return rowValue; } // // GET VALUE FROM ROW FOR NESTED RESULT MAP // private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, CacheKey combinedKey, String columnPrefix, Object partialObject) throws SQLException { final String resultMapId = resultMap.getId(); Object rowValue = partialObject; //步骤1 : 检测外层对象是否已经存在 if (rowValue != null) { final MetaObject metaObject = configuration.newMetaObject(rowValue); //步骤3.1 :将外层对象添加到ancestorObjects 集合中 putAncestor(rowValue, resultMapId); //步骤3.2 :处理嵌套映射 applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, false); //步骤3 . 3 :将外层对象从ancestorObjects 集合中移除 ancestorObjects.remove(resultMapId); } else { // 延迟加载 final ResultLoaderMap lazyLoader = new ResultLoaderMap(); //步骤2 .1 :创建外层对象 rowValue = createResultObject(rsw, resultMap, lazyLoader, columnPrefix); if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) { final MetaObject metaObject = configuration.newMetaObject(rowValue); //更新foundValues ,其含义与简单映射中同名变量相同:成功映射任意属性,则 foundValues为 true ;否则foundValues 为false boolean foundValues = this.useConstructorMappings; //步骤2.2 :自动映射 if (shouldApplyAutomaticMappings(resultMap, true)) { foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues; } //步骤2 . 3 :映射ResultMap 中明确指定的字段 foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues; //步骤2.4 :将外层对象添加到ancestorObjects 集合中 putAncestor(rowValue, resultMapId); //步骤2 . 5 :处理嵌套映射 foundValues = applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, true) || foundValues; //步骤2 . 6 :将外层对象从ancestorObjects 集合中移除 ancestorObjects.remove(resultMapId); foundValues = lazyLoader.size() > 0 || foundValues; rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null; } if (combinedKey != CacheKey.NULL_CACHE_KEY) { //步骤2.7 :将外层对象保存到nestedResultObjects 集合中,待映射后续记录时使用 nestedResultObjects.put(combinedKey, rowValue); } } return rowValue; } /** * 在ResultMap 中明确地配置了autoMapping 属性,则优先根据该属性的值决定是否开启自动映射功能。 * 如果没有配置autoMapping 属性,则在根据mybatis -config.xrnl 中<settings>节点中配置的autoMappingBehavior值(默认为PARTIAL ) * 决定是否开启自动映射功能。 * @param resultMap * @param isNested * @return */ private boolean shouldApplyAutomaticMappings(ResultMap resultMap, boolean isNested) { //获取ResultMap 中的autoMapping 属性值 if (resultMap.getAutoMapping() != null) { return resultMap.getAutoMapping(); } else { //检测是否为嵌套查询或是嵌套映射 if (isNested) { return AutoMappingBehavior.FULL == configuration.getAutoMappingBehavior(); } else { return AutoMappingBehavior.NONE != configuration.getAutoMappingBehavior(); } } } /** * 处理ResultMap中明确需要进行映射的列, 在该方法中涉及延迟加载、嵌套映射等内容 * @param rsw * @param resultMap * @param metaObject * @param lazyLoader * @param columnPrefix * @return * @throws SQLException */ private boolean applyPropertyMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException { //获取该ResultMap 中明确需要进行映射的列名集合 final List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix); boolean foundValues = false; //获取ResultMap.propertyResultMappings 集合,其中记录了映射使用的所有ResultMapping 对象 final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings(); for (ResultMapping propertyMapping : propertyMappings) { //处理列前级 String column = prependPrefix(propertyMapping.getColumn(), columnPrefix); if (propertyMapping.getNestedResultMapId() != null) { // the user added a column attribute to a nested result map, ignore it //该属性需要使用一个嵌套ResultMap 进行映射,忽略column 属性 column = null; } // 下面的逻辑主要处理三种场景 //场景1 : column 是” { propl=coll,prop2=co12 )”这种形式的,一般与嵌套查询配合使用,表示将coll 和col2的列值传递给内层嵌套查询作为参数 //场景2 :基本类型的属性映射 // 场景3 :多结果集的场景处理,该属性来自另一个结果集 if (//一-场景l propertyMapping.isCompositeResult() //一-场景2 || (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH))) //-一场景3 || propertyMapping.getResultSet() != null) { //通过getPropertyMappingValue ()方法完成映射,并得到属性值 Object value = getPropertyMappingValue(rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix); // issue #541 make property optional //获取属性名称 final String property = propertyMapping.getProperty(); if (property == null) { continue; } else if (value == DEFERRED) { foundValues = true; continue; } if (value != null) { // DEFERED 表示的是占位符对象 foundValues = true; } if (value != null || (configuration.isCallSettersOnNulls() && !metaObject.getSetterType(property).isPrimitive())) { // gcode issue #377, call setter on nulls (value is not 'found') //设置属性值 metaObject.setValue(property, value); } } } return foundValues; } private Object getPropertyMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException { //嵌套查询 if (propertyMapping.getNestedQueryId() != null) { return getNestedQueryMappingValue(rs, metaResultObject, propertyMapping, lazyLoader, columnPrefix); } else if (propertyMapping.getResultSet() != null) { //多结果集的处理 addPendingChildRelation(rs, metaResultObject, propertyMapping); // TODO is that OK? // 返回占位符对象 return DEFERRED; } else { //获取ResultMapping 中记录的Type Handler 对象 final TypeHandler<?> typeHandler = propertyMapping.getTypeHandler(); final String column = prependPrefix(propertyMapping.getColumn(), columnPrefix); // 使用TypeHandler 对象获取属性值 return typeHandler.getResult(rs, column); } } /** * 为未映射的列查找对应的属性,并将两者关联起来封装 * 成UnMappedColurnnAutoMapping 对象 * @param rsw * @param resultMap * @param metaObject * @param columnPrefix * @return * @throws SQLException */ private List<UnMappedColumnAutoMapping> createAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException { // 自动映射的缓存k ey final String mapKey = resultMap.getId() + ":" + columnPrefix; List<UnMappedColumnAutoMapping> autoMapping = autoMappingsCache.get(mapKey); // autoMappingsCache 缓存未命中 if (autoMapping == null) { autoMapping = new ArrayList<>(); //从ResultSetWrapper 中获取未映射的列名集合 final List<String> unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix); for (String columnName : unmappedColumnNames) { // 生成属性名称 String propertyName = columnName; //如果列名以列前缀开头,则属性名称为列名去除前缀删除的部分。如果明确指定了列前缀,但列名没有以列前级开头, 则跳过该列处理后面的列 if (columnPrefix != null && !columnPrefix.isEmpty()) { // When columnPrefix is specified, // ignore columns without the prefix. if (columnName.toUpperCase(Locale.ENGLISH).startsWith(columnPrefix)) { propertyName = columnName.substring(columnPrefix.length()); } else { continue; } } //在结果对象中查找指定的属性名 final String property = metaObject.findProperty(propertyName, configuration.isMapUnderscoreToCamelCase()); //检测是否存在该属性的setter 方法,注意:如果是MapWrapper , 一直返回true if (property != null && metaObject.hasSetter(property)) { if (resultMap.getMappedProperties().contains(property)) { continue; } final Class<?> propertyType = metaObject.getSetterType(property); if (typeHandlerRegistry.hasTypeHandler(propertyType, rsw.getJdbcType(columnName))) { //查找对应的TypeHandler 对象 final TypeHandler<?> typeHandler = rsw.getTypeHandler(propertyType, columnName); //创建UnMappedColumnAutoMapping 对象, 并添加到autoMapping 集合中 autoMapping.add(new UnMappedColumnAutoMapping(columnName, property, typeHandler, propertyType.isPrimitive())); } else { configuration.getAutoMappingUnknownColumnBehavior() .doAction(mappedStatement, columnName, property, propertyType); } } else { configuration.getAutoMappingUnknownColumnBehavior() .doAction(mappedStatement, columnName, (property != null) ? property : propertyName, null); } } // 将autoMapping 添加到缓存中保存 autoMappingsCache.put(mapKey, autoMapping); } return autoMapping; } private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException { //获取ResultSet 中存在, 但ResultMap 中没有明确映射的列所对应的UnMappedColumnAutoMapping 集 //合,如果ResultMap 中设置的resultType 为HashMap的话,则全部的列都会在这里获取到 List<UnMappedColumnAutoMapping> autoMapping = createAutomaticMappings(rsw, resultMap, metaObject, columnPrefix); boolean foundValues = false; if (!autoMapping.isEmpty()) { //遍历autoMapping 集合 for (UnMappedColumnAutoMapping mapping : autoMapping) { //使用TypeHandler 获取自动映射的列值 final Object value = mapping.typeHandler.getResult(rsw.getResultSet(), mapping.column); if (value != null) { foundValues = true; } if (value != null || (configuration.isCallSettersOnNulls() && !mapping.primitive)) { // gcode issue #377, call setter on nulls (value is not 'found') //将自动映射的属性位设置到结果对象中 metaObject.setValue(mapping.property, value); } } } return foundValues; } /** * 创建数据库记录映射得到的结果对象, * @param rsw * @param resultMap * @param lazyLoader * @param columnPrefix * @return * @throws SQLException */ private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException { //标识是否使用构造函数创建该结果对象 this.useConstructorMappings = false; // reset previous mapping result // 记录构造函数的参数类型 final List<Class<?>> constructorArgTypes = new ArrayList<>(); // 记录构造函数的实参 final List<Object> constructorArgs = new ArrayList<>(); //创建该行记录对应的结果对象 Object resultObject = createResultObject(rsw, resultMap, constructorArgTypes, constructorArgs, columnPrefix); if (resultObject != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) { final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings(); for (ResultMapping propertyMapping : propertyMappings) { // issue gcode #109 && issue #149 if (propertyMapping.getNestedQueryId() != null && propertyMapping.isLazy()) { //如果包含嵌套查询,且配置了延迟加载,则创建代理对象 resultObject = configuration.getProxyFactory().createProxy(resultObject, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs); break; } } } // 记录是否使用构造器创建对象 this.useConstructorMappings = resultObject != null && !constructorArgTypes.isEmpty(); // set current mapping result return resultObject; } private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, List<Class<?>> constructorArgTypes, List<Object> constructorArgs, String columnPrefix) throws SQLException { //获取ResultMap 中记录的type 属性,也就是该行记录最终映射成的结果对象类型 final Class<?> resultType = resultMap.getType(); // 创建该类型对应的MetaClass 对象 final MetaClass metaType = MetaClass.forClass(resultType, reflectorFactory); // 获取ResultMap 中记录的< constructor> 节点信息,如果该集合不为空,则可以通过该集合确定相应Java 类中的唯一构造函数 final List<ResultMapping> constructorMappings = resultMap.getConstructorResultMappings(); //创建结果对象分为下面4 种场景 //场景1 :结果集只有一列,且存在TypeHandler 对象可以将该列转换成resultType 类型的值 if (hasTypeHandlerForResultObject(rsw, resultType)) { // 先查找相应的Type Handler 对象,再使用TypeH andler 对象将该记录转换成Java 类型的值 return createPrimitiveResultObject(rsw, resultMap, columnPrefix); } else if (!constructorMappings.isEmpty()) { // ResultMap 中记录了<constructor> 节点的信息, 则通过反射方式调用构造方法,创建结果对象 return createParameterizedResultObject(rsw, resultType, constructorMappings, constructorArgTypes, constructorArgs, columnPrefix); } else if (resultType.isInterface() || metaType.hasDefaultConstructor()) { //场景3 : 使用默认的无参构造函数,则直接使用ObjectFactory 创建对象 return objectFactory.create(resultType); } else if (shouldApplyAutomaticMappings(resultMap, false)) { // 场景4 :通过自动映射的方式查找合适的构造方法并创建结果对象 return createByConstructorSignature(rsw, resultType, constructorArgTypes, constructorArgs); } throw new ExecutorException("Do not know how to create an instance of " + resultType); } Object createParameterizedResultObject(ResultSetWrapper rsw, Class<?> resultType, List<ResultMapping> constructorMappings, List<Class<?>> constructorArgTypes, List<Object> constructorArgs, String columnPrefix) { boolean foundValues = false; //遍历constructorMappings 集合,该过程中会使用constructorArgTypes 集合记录构造参数类型,使用constructorArgs 集合记录构造函数实参 for (ResultMapping constructorMapping : constructorMappings) { //获取当前构造参数的类型 final Class<?> parameterType = constructorMapping.getJavaType(); final String column = constructorMapping.getColumn(); final Object value; try { if (constructorMapping.getNestedQueryId() != null) { //存在嵌套查询,需要处理该查询,然后才能得到实参 value = getNestedQueryConstructorValue(rsw.getResultSet(), constructorMapping, columnPrefix); } else if (constructorMapping.getNestedResultMapId() != null) { //存在嵌套映射,需要先处理嵌套映射,才能得到实参 final ResultMap resultMap = configuration.getResultMap(constructorMapping.getNestedResultMapId()); value = getRowValue(rsw, resultMap, getColumnPrefix(columnPrefix, constructorMapping)); } else { //直接获取该列的位,然后经过TypeHandler 对象的转换,得到构造函数的实参 final TypeHandler<?> typeHandler = constructorMapping.getTypeHandler(); value = typeHandler.getResult(rsw.getResultSet(), prependPrefix(column, columnPrefix)); } } catch (ResultMapException | SQLException e) { throw new ExecutorException("Could not process result for mapping: " + constructorMapping, e); } //记录当前构造参数的类型 constructorArgTypes.add(parameterType); //记录当前构造参数的实际值 constructorArgs.add(value); foundValues = value != null || foundValues; } //通过ObjectFactory 调用匹配的构造函数,创建结果对象 return foundValues ? objectFactory.create(resultType, constructorArgTypes, constructorArgs) : null; } private Object createByConstructorSignature(ResultSetWrapper rsw, Class<?> resultType, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) throws SQLException { final Constructor<?>[] constructors = resultType.getDeclaredConstructors(); final Constructor<?> defaultConstructor = findDefaultConstructor(constructors); if (defaultConstructor != null) { return createUsingConstructor(rsw, resultType, constructorArgTypes, constructorArgs, defaultConstructor); } else { //遍历全部的构造方法 for (Constructor<?> constructor : constructors) { if (allowedConstructorUsingTypeHandlers(constructor, rsw.getJdbcTypes())) { return createUsingConstructor(rsw, resultType, constructorArgTypes, constructorArgs, constructor); } } } throw new ExecutorException("No constructor found in " + resultType.getName() + " matching " + rsw.getClassNames()); } private Object createUsingConstructor(ResultSetWrapper rsw, Class<?> resultType, List<Class<?>> constructorArgTypes, List<Object> constructorArgs, Constructor<?> constructor) throws SQLException { boolean foundValues = false; for (int i = 0; i < constructor.getParameterTypes().length; i++) { //获取构造函数的参数类型 Class<?> parameterType = constructor.getParameterTypes()[i]; // ResultSet 中的列名 String columnName = rsw.getColumnNames().get(i); //查找对应的TypeHandler ,并获取该列的值 TypeHandler<?> typeHandler = rsw.getTypeHandler(parameterType, columnName); Object value = typeHandler.getResult(rsw.getResultSet(), columnName); //记录构造函数的参数类型和参数值 constructorArgTypes.add(parameterType); constructorArgs.add(value); //更新foundValues 值 foundValues = value != null || foundValues; } //使用ObjectFactory 调用对应的构造方法,创建结果对象 return foundValues ? objectFactory.create(resultType, constructorArgTypes, constructorArgs) : null; } /** * 根据ResultMap 对象中记录的Discriminator 以及参与映射的列值, * 选择映射操作最终使用的ResultMap 对象,这个选择过程可能嵌套多层。 * @param rs * @param resultMap * @param columnPrefix * @return * @throws SQLException */ public ResultMap resolveDiscriminatedResultMap(ResultSet rs, ResultMap resultMap, String columnPrefix) throws SQLException { //记录已经处理过的ResultMap 的id Set<String> pastDiscriminators = new HashSet<>(); //获取ResultMap 中的Discriminator 对象 // <discriminator >节点对应生成的是Discriminator 对象并记录到ResultMap.discriminator字段中, Discriminator discriminator = resultMap.getDiscriminator(); while (discriminator != null) { //获取记录中对应列的值,其中会使用相应的TypeHandler 对象将该列转换成Java 类型 final Object value = getDiscriminatorValue(rs, discriminator, columnPrefix); //根据该列值获取对应的ResultMap的id final String discriminatedMapId = discriminator.getMapIdFor(String.valueOf(value)); if (configuration.hasResultMap(discriminatedMapId)) { //根据上述步骤获取的id ,查找相应的ResultMap 对象 resultMap = configuration.getResultMap(discriminatedMapId); //记录当前Discriminator 对象 Discriminator lastDiscriminator = discriminator; //获取ResultMap 对象中的Discriminator discriminator = resultMap.getDiscriminator(); //检测Discriminator 是否出现了环形引用 if (discriminator == lastDiscriminator || !pastDiscriminators.add(discriminatedMapId)) { break; } } else { break; } } //该ResultMap 对象为映射最终使用的ResultMap return resultMap; } private void handleRowValuesForNestedResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException { //创建DefaultResultContext final DefaultResultContext<Object> resultContext = new DefaultResultContext<>(); ResultSet resultSet = rsw.getResultSet(); // 步骤1 :定位到指定的记录行 skipRows(resultSet, rowBounds); Object rowValue = previousRowValue; //步骤2 :检测是否能继续映射结果集中剩余的记录行 while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) { //步骤3 :通过resolveDiscriminatedResultMap ()方法决定映射使用的ResultMap 对象 final ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null); //步骤4 :为该行记录生成CacheKey final CacheKey rowKey = createRowKey(discriminatedResultMap, rsw, null); //步骤5 :根据步骤4 中生成的CacheKey 查找nestedResultObjects 集合 Object partialObject = nestedResultObjects.get(rowKey); // issue #577 && #542 //步骤6 :检测resultOrdered 属性 if (mappedStatement.isResultOrdered()) { //主结果对象发生变化 /*resultOrdered 属性为true,认为返回一个主结果行时,不会发生引用nestedResultObjects集合中对象的情况。 这样就提前释放nestedResultObjects集合中的数据,避免在进行嵌套映射出现内存不足的情况。*/ if (partialObject == null && rowValue != null) { //清空nestedResultObjects 集合 nestedResultObjects.clear(); //保存主结果对象(也就是嵌套映射的外层结果对象) storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet); } //步骤7 :完成该行记录的映射返回结果对象,其中还会将结果对象添加到nestedResultObjects 集合中 rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, null, partialObject); } else { //步骤7 :完成该行记录的映射返回结果对象,其中还会将结果对象添加到nestedResultObjects 集合中 rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, null, partialObject); if (partialObject == null) { //步骤8 :保存结果对象 storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet); } } } // 对resultOrdered 属性为true 时的特殊处理,调用storeObject ()方法保存结果对象 if (rowValue != null && mappedStatement.isResultOrdered() && shouldProcessMoreRows(resultContext, rowBounds)) { storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet); previousRowValue = null; } else if (rowValue != null) { previousRowValue = rowValue; } } // // NESTED RESULT MAP (JOIN MAPPING) // private boolean applyNestedResultMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String parentPrefix, CacheKey parentRowKey, boolean newObject) { boolean foundValues = false; //追历全部ResultMapping 对象,处理其中的嵌套映射 for (ResultMapping resultMapping : resultMap.getPropertyResultMappings()) { // 获取ResultMapping.nestedResultMapid final String nestedResultMapId = resultMapping.getNestedResultMapId(); //步骤1 : 检测nestedResultMapid 和resultSet 两个字段的值 if (nestedResultMapId != null && resultMapping.getResultSet() == null) { try { //获取列前缀 final String columnPrefix = getColumnPrefix(parentPrefix, resultMapping); //步骤2 :确定嵌套映射使用的ResultMap 对象 final ResultMap nestedResultMap = getNestedResultMap(rsw.getResultSet(), nestedResultMapId, columnPrefix); //步骤3 :处理循环引用的情况 if (resultMapping.getColumnPrefix() == null) { // try to fill circular reference only when columnPrefix // is not specified for the nested result map (issue #215) Object ancestorObject = ancestorObjects.get(nestedResultMapId); if (ancestorObject != null) { if (newObject) { //将己存在的嵌 套对象设置到外层对象的相应属性中。 linkObjects(metaObject, resultMapping, ancestorObject); // issue #385 } // 若是循环引用,则不用执行下面的路径创建新对象,而是重用之前的对象 continue; } } //步骤4 : 为嵌套对象创建CacheKey 对象 final CacheKey rowKey = createRowKey(nestedResultMap, rsw, columnPrefix); //与外层对象的CacheKey 合井,得到全局唯一的CacheKey 对象。 final CacheKey combinedKey = combineKeys(rowKey, parentRowKey); //查找nestedResultObjects 集合中是否有相同的Key 的嵌套对象 Object rowValue = nestedResultObjects.get(combinedKey); boolean knownValue = rowValue != null; //步骤5 :如果外层对象中用于记录当前嵌套对象的属性为Collection 类型,且未初始化,则初始化外层对象中Collection 类型的属性 instantiateCollectionPropertyIfAppropriate(resultMapping, metaObject); // mandatory //步骤6 :根据notNullColumn 属性检测结果集中的空值 //根据<association> 、<collection>等节点的notNullColumn 属性,检测结果集中相应列 是否为空。 if (anyNotNullColumnHasValue(resultMapping, columnPrefix, rsw)) { //步骤7 :完成嵌套映射,并生成嵌套对象 rowValue = getRowValue(rsw, nestedResultMap, combinedKey, columnPrefix, rowValue); //注意,“! knownValue ”这个条件,当嵌套对象已存在于nestedResultObject 集合中 //时,说明相关列已经映射成了嵌套对象。现假设对象且中有bl 和b2 两个属性都指向了对, //象B 且这两个属性都是由同一ResultMap 进行映射的。在对一行记录进行映射时,首先 //映射的bl 属性会生成B 对象且成功赋值,而b2属性则为null if (rowValue != null && !knownValue) { //步骤8 :将步骤7 中得到的嵌套对象保存到外层对象的相应属性中 linkObjects(metaObject, resultMapping, rowValue); foundValues = true; } } } catch (SQLException e) { throw new ExecutorException("Error getting nested result map values for '" + resultMapping.getProperty() + "'. Cause: " + e, e); } } } return foundValues; } private CacheKey createRowKey(ResultMap resultMap, ResultSetWrapper rsw, String columnPrefix) throws SQLException { //创建CacheKey 对象 final CacheKey cacheKey = new CacheKey(); //将ResultMap 的ID作为CacheKey 的一部分 cacheKey.update(resultMap.getId()); //查找ResultMapping 对象集合 List<ResultMapping> resultMappings = getResultMappingsForRowKey(resultMap); //没有找到任何ResultMapping if (resultMappings.isEmpty()) { if (Map.class.isAssignableFrom(resultMap.getType())) { //由结果集中的所有列名以及当前记录行的所有列值一起构成Cache Key 对象 createRowKeyForMap(rsw, cacheKey); } else { //由结果集中未映射的列名以及它们在当前记录行中的对应列值一起构成CacheKey 对象 createRowKeyForUnmappedProperties(resultMap, rsw, cacheKey, columnPrefix); } } else { // 由resultMappings 集合中的列名以及它们在当前记录行中相应的列值一起构成CacheKey createRowKeyForMappedProperties(resultMap, rsw, cacheKey, resultMappings, columnPrefix); } if (cacheKey.getUpdateCount() < 2) { //没有找到任何列参与构成CacheKey 对象,则返回NullCacheKey 对象 return CacheKey.NULL_CACHE_KEY; } return cacheKey; } private CacheKey combineKeys(CacheKey rowKey, CacheKey parentRowKey) { if (rowKey.getUpdateCount() > 1 && parentRowKey.getUpdateCount() > 1) { CacheKey combinedKey; try { combinedKey = rowKey.clone(); } catch (CloneNotSupportedException e) { throw new ExecutorException("Error cloning cache key. Cause: " + e, e); } //与外层对象的CacheKey 合并,形成嵌套对象最终的CacheKey combinedKey.update(parentRowKey); return combinedKey; } return CacheKey.NULL_CACHE_KEY; } private List<ResultMapping> getResultMappingsForRowKey(ResultMap resultMap) { // ResultMap.idResultMappings集合中记录<id.Arg>和<id>节点对应的ResultMapping 对象 List<ResultMapping> resultMappings = resultMap.getIdResultMappings(); if (resultMappings.isEmpty()) { // ResultMap.propertyResultMappings 集合记录了除<id*> 节点之外的ResultMapping 对象 resultMappings = resultMap.getPropertyResultMappings(); } return resultMappings; } private void createRowKeyForMappedProperties(ResultMap resultMap, ResultSetWrapper rsw, CacheKey cacheKey, List<ResultMapping> resultMappings, String columnPrefix) throws SQLException { // 遥历所有resultMappings 集合 for (ResultMapping resultMapping : resultMappings) { //如果不存在嵌套映射,且忽略嵌套查询 if (resultMapping.isSimple()) { // 获取该列的名称 final String column = prependPrefix(resultMapping.getColumn(), columnPrefix); //获取该列相应的Type Handler 对象 final TypeHandler<?> th = resultMapping.getTypeHandler(); //获取映射的列名 List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix); // Issue #//4 if (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH))) { //获取列值 final Object value = th.getResult(rsw.getResultSet(), column); if (value != null || configuration.isReturnInstanceForEmptyRow()) { //将列名和列值添加到CacheKey 对象中 cacheKey.update(column); cacheKey.update(value); } } } } } private void linkObjects(MetaObject metaObject, ResultMapping resultMapping, Object rowValue) { //检查外层对象的指定属性是否为Collection类型,如果是且未初始化,则初始化该集合属性并返回 final Object collectionProperty = instantiateCollectionPropertyIfAppropriate(resultMapping, metaObject); //根据属性是否为集合类型,调用MetaObject 的相应方法,将嵌套对象记录到外层对象的相应属性中 if (collectionProperty != null) { final MetaObject targetMetaObject = configuration.newMetaObject(collectionProperty); targetMetaObject.add(rowValue); } else { metaObject.setValue(resultMapping.getProperty(), rowValue); } } private Object instantiateCollectionPropertyIfAppropriate(ResultMapping resultMapping, MetaObject metaObject) { //获取指定的属性名称和当前属性值 final String propertyName = resultMapping.getProperty(); Object propertyValue = metaObject.getValue(propertyName); //检测该属性是否已初始化 if (propertyValue == null) { //获取属性的Java 类型 Class<?> type = resultMapping.getJavaType(); if (type == null) { type = metaObject.getSetterType(propertyName); } try { //指定属性为集合类型 if (objectFactory.isCollection(type)) { //通过ObjectFactory 创建该类型的集合对象, 并进行相应设置 propertyValue = objectFactory.create(type); metaObject.setValue(propertyName, propertyValue); return propertyValue; } } catch (Exception e) { throw new ExecutorException("Error instantiating collection property for result '" + resultMapping.getProperty() + "'. Cause: " + e, e); } } else if (objectFactory.isCollection(propertyValue.getClass())) { //指定属性是集合类型且已经初始化,则返回该属性位 return propertyValue; } return null; } } # 嵌套查询&延迟加载 # ## ResultLoader ## public class ResultLoader { //Configuration 配置对象 protected final Configuration configuration; //用于执行延迟加载操作的Executor 对象 protected final Executor executor; protected final MappedStatement mappedStatement; // 记录了延迟执行的SQL 语句的实参 protected final Object parameterObject; // 记录了延迟加载得到的对象类型 protected final Class<?> targetType; // ObjectFactory 工厂对象,通过反射创建延迟加载的Java 对象 protected final ObjectFactory objectFactory; // CacheKey 对象 protected final CacheKey cacheKey; //记录了延迟执行的S QL 语句以及相关配置信息 protected final BoundSql boundSql; // ResultExtractor 负责将延迟加载得到的结果对象转换成target Type 类型的对象 protected final ResultExtractor resultExtractor; // 创建ResultLoader 的线程id protected final long creatorThreadId; protected boolean loaded; // 延迟加载得到的结果对象 protected Object resultObject; public Object loadResult() throws SQLException { //执行延迟加载,得到结果对象,并以List 的形式返回 List<Object> list = selectList(); //将list 集合转换成targetType 指定类型的对象 resultObject = resultExtractor.extractObjectFromList(list, targetType); return resultObject; } private <E> List<E> selectList() throws SQLException { // 记录执行延迟加载的Executor 对象 Executor localExecutor = executor; //检测调用该方法的线程是否为创建ResultLoader 对象的线程、检测localExecutor 是否 //关闭,检测到异常情况时,会创建新的Executor 对象来执行延迟加载操作 if (Thread.currentThread().getId() != this.creatorThreadId || localExecutor.isClosed()) { localExecutor = newExecutor(); } try { //执行查询操作,得到延迟加载的对象。 return localExecutor.query(mappedStatement, parameterObject, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER, cacheKey, boundSql); } finally { if (localExecutor != executor) { //如果是在selectList()方法中新建的Executor 对象,则需要关闭 localExecutor.close(false); } } } } ## ResultLoaderMap ## public class ResultLoaderMap { //保存对象中延迟加载属性及其对应的ResultLoader 对象之间的关系, private final Map<String, LoadPair> loaderMap = new HashMap<>(); public boolean load(String property) throws SQLException { //从loaderMap 集合中移除指定的属性 LoadPair pair = loaderMap.remove(property.toUpperCase(Locale.ENGLISH)); if (pair != null) { //执行延迟加载 pair.load(); return true; } return false; } /** * 加载指定名称的属性 * @throws SQLException */ public void loadAll() throws SQLException { final Set<String> methodNameSet = loaderMap.keySet(); String[] methodNames = methodNameSet.toArray(new String[methodNameSet.size()]); for (String methodName : methodNames) { // 加载loaderMap 集合中记录的全部属性 load(methodName); } } public static class LoadPair implements Serializable { private static final long serialVersionUID = 20130412; /** * Name of factory method which returns database connection. */ private static final String FACTORY_METHOD = "getConfiguration"; /** * Object to check whether we went through serialization.. */ private final transient Object serializationCheck = new Object(); /** * Meta object which sets loaded properties. * 外层对象( 一般是外层对象的代理对象)对应的MetaObject 对象 */ private transient MetaObject metaResultObject; /** * Result loader which loads unread properties. * 负责加载延迟加载属性的ResultLoader 对象 */ private transient ResultLoader resultLoader; /** * Wow, logger. */ private transient Log log; /** * Factory class through which we get database connection. */ private Class<?> configurationFactory; /** * Name of the unread property. * 延迟加载的属性名称 */ private String property; /** * ID of SQL statement which loads the property. * 用于加载属性的SQL 语句的ID */ private String mappedStatement; /** * Parameter of the sql statement. */ private Serializable mappedParameter; private LoadPair(final String property, MetaObject metaResultObject, ResultLoader resultLoader) { this.property = property; this.metaResultObject = metaResultObject; this.resultLoader = resultLoader; /* Save required information only if original object can be serialized. */ if (metaResultObject != null && metaResultObject.getOriginalObject() instanceof Serializable) { final Object mappedStatementParameter = resultLoader.parameterObject; /* @todo May the parameter be null? */ if (mappedStatementParameter instanceof Serializable) { this.mappedStatement = resultLoader.mappedStatement.getId(); this.mappedParameter = (Serializable) mappedStatementParameter; this.configurationFactory = resultLoader.configuration.getConfigurationFactory(); } else { Log log = this.getLogger(); if (log.isDebugEnabled()) { log.debug("Property [" + this.property + "] of [" + metaResultObject.getOriginalObject().getClass() + "] cannot be loaded " + "after deserialization. Make sure it's loaded before serializing " + "forenamed object."); } } } } public void load() throws SQLException { /* These field should not be null unless the loadpair was serialized. * Yet in that case this method should not be called. */ if (this.metaResultObject == null) { throw new IllegalArgumentException("metaResultObject is null"); } if (this.resultLoader == null) { throw new IllegalArgumentException("resultLoader is null"); } this.load(null); } public void load(final Object userObject) throws SQLException { if (this.metaResultObject == null || this.resultLoader == null) { if (this.mappedParameter == null) { throw new ExecutorException("Property [" + this.property + "] cannot be loaded because " + "required parameter of mapped statement [" + this.mappedStatement + "] is not serializable."); } final Configuration config = this.getConfiguration(); final MappedStatement ms = config.getMappedStatement(this.mappedStatement); if (ms == null) { throw new ExecutorException("Cannot lazy load property [" + this.property + "] of deserialized object [" + userObject.getClass() + "] because configuration does not contain statement [" + this.mappedStatement + "]"); } this.metaResultObject = config.newMetaObject(userObject); this.resultLoader = new ResultLoader(config, new ClosedExecutor(), ms, this.mappedParameter, metaResultObject.getSetterType(this.property), null, null); } /* We are using a new executor because we may be (and likely are) on a new thread * and executors aren't thread safe. (Is this sufficient?) * * A better approach would be making executors thread safe. */ if (this.serializationCheck == null) { final ResultLoader old = this.resultLoader; this.resultLoader = new ResultLoader(old.configuration, new ClosedExecutor(), old.mappedStatement, old.parameterObject, old.targetType, old.cacheKey, old.boundSql); } //执行延迟加载,并将加载得到的嵌套对象设置到外层对象中 this.metaResultObject.setValue(property, this.resultLoader.loadResult()); } } } ## ResultExtractor ## public class ResultExtractor { public Object extractObjectFromList(List<Object> list, Class<?> targetType) { Object value = null; // 如果目标对象类型为List ,则无须转换。 if (targetType != null && targetType.isAssignableFrom(list.getClass())) { value = list; } else if (targetType != null && objectFactory.isCollection(targetType)) { //如果目标对象类型是Collection 子类、数组类型(其中项可以是基本类型,也可以是 // 对象类型),则创建targetType 类型的集合对象,并复制List< Object> 中的项。 value = objectFactory.create(targetType); MetaObject metaObject = configuration.newMetaObject(value); metaObject.addAll(list); } else if (targetType != null && targetType.isArray()) { Class<?> arrayComponentType = targetType.getComponentType(); Object array = Array.newInstance(arrayComponentType, list.size()); if (arrayComponentType.isPrimitive()) { for (int i = 0; i < list.size(); i++) { Array.set(array, i, list.get(i)); } value = array; } else { value = list.toArray((Object[])array); } } else { if (list != null && list.size() > 1) { throw new ExecutorException("Statement returned more than one row, where no more than one was expected."); } else if (list != null && list.size() == 1) { //如果目标对象是普通Java 对象且延迟加载得到的List 大小为1 ,则认为将其中唯一的 //项作为转换后的对象返回。 value = list.get(0); } } return value; } } ## ProxyFactory ## public interface ProxyFactory { //根据配置初始化ProxyFactory对象, MyBatis提供的两个子类中,该方法都是空实现 default void setProperties(Properties properties) { // NOP } //createProxy ()方法用于创建代理对象 Object createProxy(Object target, ResultLoaderMap lazyLoader, Configuration configuration, ObjectFactory objectFactory, List<Class<?>> constructorArgTypes, List<Object> constructorArgs); } ## CglibProxyFactory ## public class CglibProxyFactory implements ProxyFactory { static Object crateProxy(Class<?> type, Callback callback, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) { Enhancer enhancer = new Enhancer(); enhancer.setCallback(callback); enhancer.setSuperclass(type); try { //查找名为” writeReplace ”的方法,查找不到writeReplace () 方法,则添加 //WriteReplaceinterface 接口,该接口中定义了writeReplace方法 type.getDeclaredMethod(WRITE_REPLACE_METHOD); // ObjectOutputStream will call writeReplace of objects returned by writeReplace if (LogHolder.log.isDebugEnabled()) { LogHolder.log.debug(WRITE_REPLACE_METHOD + " method was found on bean " + type + ", make sure it returns this"); } } catch (NoSuchMethodException e) { enhancer.setInterfaces(new Class[] { WriteReplaceInterface.class }); } catch (SecurityException e) { // nothing to do here } //根据构造方法的参数列表,调用相应的Enhancer.create()方法,创建代理对象 Object enhanced; if (constructorArgTypes.isEmpty()) { enhanced = enhancer.create(); } else { Class<?>[] typesArray = constructorArgTypes.toArray(new Class[constructorArgTypes.size()]); Object[] valuesArray = constructorArgs.toArray(new Object[constructorArgs.size()]); enhanced = enhancer.create(typesArray, valuesArray); } return enhanced; } private static class EnhancedResultObjectProxyImpl implements MethodInterceptor { //需要创建代理的目标类 private final Class<?> type; // ResultLoaderMap 对象,其中记录了延迟加载的属性名称与对应ResultLoader 对象之间的关系 private final ResultLoaderMap lazyLoader; // 在mybatis-config.xml 文件中, aggressiveLazyLoading 配置项的值 private final boolean aggressive; //触发延迟加载的方法名列表,如果调用了该列表中的方法,则对全部的延迟加载属性进行加载操作 private final Set<String> lazyLoadTriggerMethods; private final ObjectFactory objectFactory; //创建代理对象时,使用的构造方法的参数类型和参数值 private final List<Class<?>> constructorArgTypes; private final List<Object> constructorArgs; private EnhancedResultObjectProxyImpl(Class<?> type, ResultLoaderMap lazyLoader, Configuration configuration, ObjectFactory objectFactory, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) { this.type = type; this.lazyLoader = lazyLoader; this.aggressive = configuration.isAggressiveLazyLoading(); this.lazyLoadTriggerMethods = configuration.getLazyLoadTriggerMethods(); this.objectFactory = objectFactory; this.constructorArgTypes = constructorArgTypes; this.constructorArgs = constructorArgs; } public static Object createProxy(Object target, ResultLoaderMap lazyLoader, Configuration configuration, ObjectFactory objectFactory, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) { final Class<?> type = target.getClass(); EnhancedResultObjectProxyImpl callback = new EnhancedResultObjectProxyImpl(type, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs); //调用CglibProxyFactory . crateProxy ()方法创建代理对象 Object enhanced = crateProxy(type, callback, constructorArgTypes, constructorArgs); //将target 对象中的属性值复制到代理对象的对应属性中 PropertyCopier.copyBeanProperties(type, target, enhanced); return enhanced; } @Override public Object intercept(Object enhanced, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { final String methodName = method.getName(); try { synchronized (lazyLoader) { if (WRITE_REPLACE_METHOD.equals(methodName)) { //调用的方法名为” writeReplace ”的相关处理 Object original; if (constructorArgTypes.isEmpty()) { original = objectFactory.create(type); } else { original = objectFactory.create(type, constructorArgTypes, constructorArgs); } PropertyCopier.copyBeanProperties(type, enhanced, original); if (lazyLoader.size() > 0) { return new CglibSerialStateHolder(original, lazyLoader.getProperties(), objectFactory, constructorArgTypes, constructorArgs); } else { return original; } } else { //检测是否存在延迟加载的属性,以及调用方法名是否为” finalize ” if (lazyLoader.size() > 0 && !FINALIZE_METHOD.equals(methodName)) { //如果aggressiveLazyLoading 配置为true ,或是调用方法的名称存在于 //lazyLoadTriggerMethods 列表中,则将全部的属性都加载完成 if (aggressive || lazyLoadTriggerMethods.contains(methodName)) { lazyLoader.loadAll(); } else if (PropertyNamer.isSetter(methodName)) { final String property = PropertyNamer.methodToProperty(methodName); lazyLoader.remove(property); } else if (PropertyNamer.isGetter(methodName)) { //如果调用了某属性的getter 方法,先获取该属性的名称 final String property = PropertyNamer.methodToProperty(methodName); //检测是否为延迟加载的属性 if (lazyLoader.hasLoader(property)) { //触发该属性的加载操作 lazyLoader.load(property); } } } } } // 调用目标对象的方法 return methodProxy.invokeSuper(enhanced, args); } catch (Throwable t) { throw ExceptionUtil.unwrapThrowable(t); } } } } ## 调用懒加载 ## public class DefaultResultSetHandler implements ResultSetHandler { private Object getNestedQueryConstructorValue(ResultSet rs, ResultMapping constructorMapping, String columnPrefix) throws SQLException { //获取嵌套查询的id 以及对应的MappedStatement 对象 final String nestedQueryId = constructorMapping.getNestedQueryId(); final MappedStatement nestedQuery = configuration.getMappedStatement(nestedQueryId); final Class<?> nestedQueryParameterType = nestedQuery.getParameterMap().getType(); //获取传递给嵌套查询的参数值 final Object nestedQueryParameterObject = prepareParameterForNestedQuery(rs, constructorMapping, nestedQueryParameterType, columnPrefix); Object value = null; //在创建构造函数的参数时涉及的嵌套查询,无论配置如何,都不会延迟加载 if (nestedQueryParameterObject != null) { //获取嵌套查询对应的BoundSql 对象和相应的CacheKey 对象 final BoundSql nestedBoundSql = nestedQuery.getBoundSql(nestedQueryParameterObject); final CacheKey key = executor.createCacheKey(nestedQuery, nestedQueryParameterObject, RowBounds.DEFAULT, nestedBoundSql); //获取嵌套查询结果集经过映射后的目标类型 final Class<?> targetType = constructorMapping.getJavaType(); //创建ResultLoader 对象,并调用loadResult ()方法执行嵌套查询,得到相应的构造方法参数值 final ResultLoader resultLoader = new ResultLoader(configuration, executor, nestedQuery, nestedQueryParameterObject, targetType, key, nestedBoundSql); value = resultLoader.loadResult(); } return value; } private Object getNestedQueryMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException { //获取嵌套查询的id 和对应的MappedStatement 对象 final String nestedQueryId = propertyMapping.getNestedQueryId(); final String property = propertyMapping.getProperty(); //获取传递给嵌套查询的参数类型和参数值 final MappedStatement nestedQuery = configuration.getMappedStatement(nestedQueryId); final Class<?> nestedQueryParameterType = nestedQuery.getParameterMap().getType(); final Object nestedQueryParameterObject = prepareParameterForNestedQuery(rs, propertyMapping, nestedQueryParameterType, columnPrefix); Object value = null; if (nestedQueryParameterObject != null) { // 获取嵌套查询对应的BoundSql 对象和相应CacheKey 对象 final BoundSql nestedBoundSql = nestedQuery.getBoundSql(nestedQueryParameterObject); final CacheKey key = executor.createCacheKey(nestedQuery, nestedQueryParameterObject, RowBounds.DEFAULT, nestedBoundSql); //获取嵌套查询结果集经过映射后的目标类型 final Class<?> targetType = propertyMapping.getJavaType(); //检测缓存中是否存在该嵌套查询的结果对象 if (executor.isCached(nestedQuery, key)) { //创建DeferredLoad 对象,并通过该DeferredLoad 对象从缓存中加载结果对象 executor.deferLoad(nestedQuery, metaResultObject, property, key, targetType); value = DEFERRED; } else { //创建嵌套查询相应的ResultLoader 对象 final ResultLoader resultLoader = new ResultLoader(configuration, executor, nestedQuery, nestedQueryParameterObject, targetType, key, nestedBoundSql); if (propertyMapping.isLazy()) { //如果该属性配置了延迟加载,则将其添加到ResultLoaderMap 中,等待真正使用时 //再执行嵌套查询并得到结果对象 lazyLoader.addLoader(property, metaResultObject, resultLoader); value = DEFERRED; } else { //没有配置延迟加载, 则直接调用ResultLoader.loadResult ()方法执行嵌套查询,并 // 映射得到结果对象 value = resultLoader.loadResult(); } } } return value; } /** * 创建数据库记录映射得到的结果对象, * @param rsw * @param resultMap * @param lazyLoader * @param columnPrefix * @return * @throws SQLException */ private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException { //标识是否使用构造函数创建该结果对象 this.useConstructorMappings = false; // reset previous mapping result // 记录构造函数的参数类型 final List<Class<?>> constructorArgTypes = new ArrayList<>(); // 记录构造函数的实参 final List<Object> constructorArgs = new ArrayList<>(); //创建该行记录对应的结果对象 Object resultObject = createResultObject(rsw, resultMap, constructorArgTypes, constructorArgs, columnPrefix); if (resultObject != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) { final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings(); for (ResultMapping propertyMapping : propertyMappings) { // issue gcode #109 && issue #149 //如果存在嵌套查询且该属性为主且这加载的属性,则使用ProxyFactory 创建代理对象, if (propertyMapping.getNestedQueryId() != null && propertyMapping.isLazy()) { //如果包含嵌套查询,且配置了延迟加载,则创建代理对象 resultObject = configuration.getProxyFactory().createProxy(resultObject, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs); break; } } } // 记录是否使用构造器创建对象 this.useConstructorMappings = resultObject != null && !constructorArgTypes.isEmpty(); // set current mapping result return resultObject; } } # 多结果集处理 # public class DefaultResultSetHandler implements ResultSetHandler { private void addPendingChildRelation(ResultSet rs, MetaObject metaResultObject, ResultMapping parentMapping) throws SQLException { //步骤1 、为指定结果集创建CacheKey 对象 CacheKey cacheKey = createKeyForMultipleResults(rs, parentMapping, parentMapping.getColumn(), parentMapping.getColumn()); //步骤2 、创建PendingRelation 对象 PendingRelation deferLoad = new PendingRelation(); deferLoad.metaObject = metaResultObject; deferLoad.propertyMapping = parentMapping; //步骤3 、将PendingRelation 对象添加到pendingRelations 集合缓存 List<PendingRelation> relations = pendingRelations.computeIfAbsent(cacheKey, k -> new ArrayList<>()); // issue #255 relations.add(deferLoad); //步骤4 、在nextResultMaps 集合记录指定属性对应的结果集名称以及对应的ResultMapping 对象 ResultMapping previous = nextResultMaps.get(parentMapping.getResultSet()); if (previous == null) { nextResultMaps.put(parentMapping.getResultSet(), parentMapping); } else { // 如果同名的结果集对应不同的ResultMapping,抛出异常 if (!previous.equals(parentMapping)) { throw new ExecutorException("Two different properties are mapped to the same resultSet"); } } } private CacheKey createKeyForMultipleResults(ResultSet rs, ResultMapping resultMapping, String names, String columns) throws SQLException { CacheKey cacheKey = new CacheKey(); //添加ResultMapping cacheKey.update(resultMapping); if (columns != null && names != null) { //按照逗号切分列名 String[] columnsArray = columns.split(","); String[] namesArray = names.split(","); for (int i = 0; i < columnsArray.length; i++) { //查询该行记录对应列的值 Object value = rs.getString(columnsArray[i]); if (value != null) { //添加列名和列值 cacheKey.update(namesArray[i]); cacheKey.update(value); } } } return cacheKey; } /** * 处理Statement 、PreparedStatement 产生的结果集,还可以处理 * Callab leStatement 调用存储过程产生的多结果集。 * @param stmt * @return * @throws SQLException */ @Override public List<Object> handleResultSets(Statement stmt) throws SQLException { ErrorContext.instance().activity("handling results").object(mappedStatement.getId()); //保存映射结果集得到的结果对象 final List<Object> multipleResults = new ArrayList<>(); int resultSetCount = 0; // 获取第一个ResultSet 对象,可能存在多个ResultSet ,这里只获取第一个ResultSet ResultSetWrapper rsw = getFirstResultSet(stmt); List<ResultMap> resultMaps = mappedStatement.getResultMaps(); int resultMapCount = resultMaps.size(); validateResultMapsCount(rsw, resultMapCount); //结果集不为空,则resultMaps 集合不能为空, //遍历resultMaps 集合 while (rsw != null && resultMapCount > resultSetCount) { //获取该结果集对应的ResultMap 对象 ResultMap resultMap = resultMaps.get(resultSetCount); //根据ResultMap 中定义的映射规则对ResultSet 进行映射, 并将映射的结果对象添加到 multipleResults 集合中保存 //将未解析的结果集保存nextResultMaps暂存 handleResultSet(rsw, resultMap, multipleResults, null); //获取下一个结果集 rsw = getNextResultSet(stmt); //清空nestedResultObjects 集合 cleanUpAfterHandlingResultSet(); // 递增resultSetCount resultSetCount++; } //获取MappedStatement.resultSets属性。该属性仅对多结果集的情况适用,该属性将列出语句执 //行后返回的结果集,并给每个结果集一个名称,名称是逗号分隔的 String[] resultSets = mappedStatement.getResultSets(); if (resultSets != null) { while (rsw != null && resultSetCount < resultSets.length) { //根据resultSet 的名称,获取未处理的ResultMapping ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]); if (parentMapping != null) { //获取映射该结果集要使用的ResultMap 对象 String nestedResultMapId = parentMapping.getNestedResultMapId(); ResultMap resultMap = configuration.getResultMap(nestedResultMapId); //根据ResultMap 对象映射结果集 handleResultSet(rsw, resultMap, null, parentMapping); } // 获取下一个结果集 rsw = getNextResultSet(stmt); // 清空nestedResultObjects 集合 cleanUpAfterHandlingResultSet(); // 递增resultSetCount resultSetCount++; } } return collapseSingleResultList(multipleResults); } private void linkToParents(ResultSet rs, ResultMapping parentMapping, Object rowValue) throws SQLException { // 创建CacheKey 对象。注意这里构成CacheKey 的第三部分,它换成了外键的值 CacheKey parentKey = createKeyForMultipleResults(rs, parentMapping, parentMapping.getColumn(), parentMapping.getForeignColumn()); //获取pendingRelations 集合中parentKey 对应的PendingRelation 对象 List<PendingRelation> parents = pendingRelations.get(parentKey); if (parents != null) { //遍历PendingRelations 集合 for (PendingRelation parent : parents) { if (parent != null && rowValue != null) { //将当前记录的结果对象添加到外层对象的相应属性中 linkObjects(parent.metaObject, parent.propertyMapping, rowValue); } } } } } # 游标 # public class DefaultResultSetHandler implements ResultSetHandler { /** * 在数据库查询结束之后,将 * 结果集对应的ResultSetWrapper 对象以及映射使用的ResultMap 对象封装成DefaultCursor 对象 * 井返回。 */ @Override public <E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException { ErrorContext.instance().activity("handling cursor results").object(mappedStatement.getId()); //获取结果集并封装成ResultSetWrapper 对象 ResultSetWrapper rsw = getFirstResultSet(stmt); //获取映射使用的ResultMap 对象集合 List<ResultMap> resultMaps = mappedStatement.getResultMaps(); int resultMapCount = resultMaps.size(); //边界检测,只能映射一个结果集,所以只能存在一个ResultMap 对象 validateResultMapsCount(rsw, resultMapCount); if (resultMapCount != 1) { throw new ExecutorException("Cursor results cannot be mapped to multiple resultMaps"); } //使用第一个ResultMap 对象 ResultMap resultMap = resultMaps.get(0); //将ResultSetWrapper 对象、映射使用的ResultMap 对象以及控制映射的起止位置的RowBounds // 对象封装成DefaultCursor 对象 return new DefaultCursor<>(this, resultMap, rsw, rowBounds); } } ## DefaultCursor ## public class DefaultCursor<T> implements Cursor<T> { // ResultSetHandler stuff //用于完成映射的DefaultResultSetHandler 对象 private final DefaultResultSetHandler resultSetHandler; //映射使用的Re sultMap 对象 private final ResultMap resultMap; //其中封装了结果集的相关元信息 private final ResultSetWrapper rsw; //指定了对结果集进行映射的起止位置 private final RowBounds rowBounds; //继承了ResultHandler 接口,与DefaultResultHandler类似,用于暂存映射的结果对象 protected final ObjectWrapperResultHandler<T> objectWrapperResultHandler = new ObjectWrapperResultHandler<>(); //通过该迭代器获取映射得到的结果对象 private final CursorIterator cursorIterator = new CursorIterator(); //标识是否正在迭代结果集 private boolean iteratorRetrieved; private CursorStatus status = CursorStatus.CREATED; //记录已经完成映射的行数 private int indexWithRowBound = -1; protected T fetchNextUsingRowBound() { //映射一行数据库记录,得到结果对象 T result = fetchNextObjectFromDatabase(); //从结果集开始一条条记录映射,但是将RowBounds.offset 之前的映射结果全部忽略 while (objectWrapperResultHandler.fetched && indexWithRowBound < rowBounds.getOffset()) { result = fetchNextObjectFromDatabase(); } return result; } protected T fetchNextObjectFromDatabase() { //检测当前游标对象是否关闭 if (isClosed()) { return null; } try { objectWrapperResultHandler.fetched = false; // 更新游标状态 status = CursorStatus.OPEN; if (!rsw.getResultSet().isClosed()) { resultSetHandler.handleRowValues(rsw, resultMap, objectWrapperResultHandler, RowBounds.DEFAULT, null); } } catch (SQLException e) { throw new RuntimeException(e); } // 获取结果对象 T next = objectWrapperResultHandler.result; if (objectWrapperResultHandler.fetched) { // 统计返回的结果对象数量 indexWithRowBound++; } // No more object or limit reached //检测是否还存在需要映射的记录,如果没有,如l 关闭游标并修改状态 if (!objectWrapperResultHandler.fetched || getReadItemsCount() == rowBounds.getOffset() + rowBounds.getLimit()) { //关闭结果集以及对应的Statement 对象 close(); status = CursorStatus.CONSUMED; } objectWrapperResultHandler.result = null; // 返回结果对象 return next; } protected class CursorIterator implements Iterator<T> { @Override public T next() { // Fill next with object fetched from hasNext() //在hasNext ()方法中也会调用fetchNextUsingRowBound ()方法,并将映射结果对象记录到object 字段中 T next = object; if (!objectWrapperResultHandler.fetched) { // 对结果集进行映射的核心 next = fetchNextUsingRowBound(); } if (objectWrapperResultHandler.fetched) { objectWrapperResultHandler.fetched = false; object = null; //记录返回结果对象的个数 iteratorIndex++; return next; } throw new NoSuchElementException(); } } } # 存储过程中输出参数的相关处理 # public class DefaultResultSetHandler implements ResultSetHandler { private void handleRefCursorOutputParameter(ResultSet rs, ParameterMapping parameterMapping, MetaObject metaParam) throws SQLException { if (rs == null) { return; } try { //获取映射使用的ResultMap 对象 final String resultMapId = parameterMapping.getResultMapId(); final ResultMap resultMap = configuration.getResultMap(resultMapId); final ResultSetWrapper rsw = new ResultSetWrapper(rs, configuration); if (this.resultHandler == null) { //创建用于保存映射结采对象的DefaultResultHandler 对象 final DefaultResultHandler resultHandler = new DefaultResultHandler(objectFactory); //通过handleRowValues ()方法完成映射操作,并将结果对象保存到DefaultResultHand ler 中 handleRowValues(rsw, resultMap, resultHandler, new RowBounds(), null); //将映射得到的结果对象保存 parameterObject 中 metaParam.setValue(parameterMapping.getProperty(), resultHandler.getResultList()); } else { handleRowValues(rsw, resultMap, resultHandler, new RowBounds(), null); } } finally { // issue #228 (close resultsets) closeResultSet(rs); } } @Override public void handleOutputParameters(CallableStatement cs) throws SQLException { //获取用户传入的实际参数,并为其创建相应的MetaObject 对象 final Object parameterObject = parameterHandler.getParameterObject(); final MetaObject metaParam = configuration.newMetaObject(parameterObject); //获取BoundSql . parameterMappings 集合, 其中记录了参数相关信息 final List<ParameterMapping> parameterMappings = boundSql.getParameterMappings(); //遍历所有参数信息 for (int i = 0; i < parameterMappings.size(); i++) { final ParameterMapping parameterMapping = parameterMappings.get(i); if (parameterMapping.getMode() == ParameterMode.OUT || parameterMapping.getMode() == ParameterMode.INOUT) { //如果存在输出类型的参数, 则解析参数值,并设置到parameterObject 中 if (ResultSet.class.equals(parameterMapping.getJavaType())) { //如果指定该输出参数为ResultSet 类型,则需要进行映射 handleRefCursorOutputParameter((ResultSet) cs.getObject(i + 1), parameterMapping, metaParam); } else { //使用TypeHandler 获取参数值,并设置到parameterObject 中 final TypeHandler<?> typeHandler = parameterMapping.getTypeHandler(); metaParam.setValue(parameterMapping.getProperty(), typeHandler.getResult(cs, i + 1)); } } } } } # KeyGenerator # ## KeyGenerator ## public interface KeyGenerator { //在执行insert 之前执行,设置属性order= ” BEFORE ” void processBefore(Executor executor, MappedStatement ms, Statement stmt, Object parameter); //在执行insert 之后执行,设置属性order= ” AFTER ” void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter); } public class XMLStatementBuilder extends BaseBuilder { public void parseStatementNode() { // SQL 节点下存在< selectKey >节点 if (configuration.hasKeyGenerator(keyStatementId)) { keyGenerator = configuration.getKeyGenerator(keyStatementId); } else { //根据SQL 节点的useGeneratedKeys 属性值、mybatis-config.xml 中全局的useGeneratedKeys //配置,以及是否为insert 语句, 决定使用的KeyGenerator 接口实现 keyGenerator = context.getBooleanAttribute("useGeneratedKeys", configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType)) ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE; } } } ## Jdbc3KeyGenerator ## /** * @author Clinton Begin * @author Kazuki Shimizu * 取回数据库生成的自增id ,它对应于mybatis-config.xml 配置文件 * 中的useGeneratedKeys 全局配置,以及映射配置文件中SQL 节点(<insert> 节点)的 * useGeneratedKeys 属性 */ public class Jdbc3KeyGenerator implements KeyGenerator { @Override public void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter) { //将用户传入的实参parameter 封装成集合类型, 然后传入processBatch)方法中处理 processBatch(ms, stmt, parameter); } public void processBatch(MappedStatement ms, Statement stmt, Object parameter) { //获得keyProperties 属性指定的属性名称,它表示主键对应的属性名称 final String[] keyProperties = ms.getKeyProperties(); if (keyProperties == null || keyProperties.length == 0) { return; } //获取数据库自动生成的主键,如采没有生成主键,则返回结采集为空 try (ResultSet rs = stmt.getGeneratedKeys()) { //获取ResultSet 的元数据信息 final ResultSetMetaData rsmd = rs.getMetaData(); final Configuration configuration = ms.getConfiguration(); //检测数据库生成的主键的列数与keyProperties 属性指定的列数是否匹配 if (rsmd.getColumnCount() < keyProperties.length) { // Error? } else { assignKeys(configuration, rs, rsmd, keyProperties, parameter); } } catch (Exception e) { throw new ExecutorException("Error getting generated key or setting result to parameter object. Cause: " + e, e); } } } ## SelectKeyGenerator ## /** * @author Clinton Begin * @author Jeff Butler * 主要用于生成主键,它会执行映射配置文件中定义的< selectKey>节点的SQL * 语句,该语句会获取insert 语句所需要的主键。 */ public class SelectKeyGenerator implements KeyGenerator { public static final String SELECT_KEY_SUFFIX = "!selectKey"; // 标识< selectKey >节点中定义的SQL 语句是在insert语句之前执行还是之后执行 private final boolean executeBefore; //<selectKey> 节点中定义的SQL 语句所对应的MappedStatement 对象 // 获取insert语句中使用的主键 private final MappedStatement keyStatement; private void processGeneratedKeys(Executor executor, MappedStatement ms, Object parameter) { try { if (parameter != null && keyStatement != null && keyStatement.getKeyProperties() != null) { //获取<selectKey> 节点的keyProperties配置的属性名称,它表示主键对应的属性 String[] keyProperties = keyStatement.getKeyProperties(); final Configuration configuration = ms.getConfiguration(); // 创建用户传入的实参对象对应的MetaObject 对象 final MetaObject metaParam = configuration.newMetaObject(parameter); // Do not close keyExecutor. // The transaction will be closed by parent executor. //创建Executor 对象,并执行keyStatement 字段中记录的SQL 语句,并得到主键对象 Executor keyExecutor = configuration.newExecutor(executor.getTransaction(), ExecutorType.SIMPLE); List<Object> values = keyExecutor.query(keyStatement, parameter, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER); if (values.size() == 0) { throw new ExecutorException("SelectKey returned no data."); } else if (values.size() > 1) { throw new ExecutorException("SelectKey returned more than one value."); } else { MetaObject metaResult = configuration.newMetaObject(values.get(0)); if (keyProperties.length == 1) { if (metaResult.hasGetter(keyProperties[0])) { //从主键对象中获取指定属性,设直到用户参数的对应属性中 setValue(metaParam, keyProperties[0], metaResult.getValue(keyProperties[0])); } else { // no getter for the property - maybe just a single value object // so try that //如果主键对象不包含指定属性的g etter 方法,可能是一个基本类型,直接将主键对象设 //置到用户参数中 setValue(metaParam, keyProperties[0], values.get(0)); } } else { //处理主键有多列的情况,其实现是从主键对象中取出指定属性,并设直到用户参数的对应属性中 handleMultipleProperties(keyProperties, metaParam, metaResult); } } } } catch (ExecutorException e) { throw e; } catch (Exception e) { throw new ExecutorException("Error selecting key or setting result to parameter object. Cause: " + e, e); } } } # StatementHandler # public interface StatementHandler { // 从连接中获取一个Statement Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException; // 绑定statement执行时所需的实参 void parameterize(Statement statement) throws SQLException; // 批量执行SQL 语句 void batch(Statement statement) throws SQLException; // 执行update/insert/delete 语句 int update(Statement statement) throws SQLException; // 执行select 语句 <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException; <E> Cursor<E> queryCursor(Statement statement) throws SQLException; BoundSql getBoundSql(); ParameterHandler getParameterHandler(); } ## BaseStatementHandler ## public abstract class BaseStatementHandler implements StatementHandler { protected final Configuration configuration; protected final ObjectFactory objectFactory; protected final TypeHandlerRegistry typeHandlerRegistry; // 记录使用的ResultSetHandler 对象, 它的主要功能是将结采集映射成结采对象 protected final ResultSetHandler resultSetHandler; // 记录使用的ParameterHandler 对象, ParameterHandler 的主要功能是为SQL 语句绑定实参,也就是 // 使用传入的实参替换SQL t吾句的中’ ? ”占位符 protected final ParameterHandler parameterHandler; // 记录执行SQL 语句的Executor 对象 protected final Executor executor; // 记录SQL t吾句对应的MappedStatement 和BoundSql 对象 protected final MappedStatement mappedStatement; //RowBounds 记录了用户设置的offset 和limit ,用于在结采集中定位映射的起始位置和结束位置 protected final RowBounds rowBounds; protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { this.configuration = mappedStatement.getConfiguration(); this.executor = executor; this.mappedStatement = mappedStatement; this.rowBounds = rowBounds; this.typeHandlerRegistry = configuration.getTypeHandlerRegistry(); this.objectFactory = configuration.getObjectFactory(); if (boundSql == null) { // issue #435, get the key before calculating the statement //调用KeyGenerator.processBefore()方法获取主键 generateKeys(parameterObject); boundSql = mappedStatement.getBoundSql(parameterObject); } this.boundSql = boundSql; this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql); this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql); } } ## DefaultParameterHandler ## /** * @author Clinton Begin * @author Eduardo Macarron */ public class DefaultParameterHandler implements ParameterHandler { //TypeHandlerRegistry 对象,管理MyBatis中的全部TypeHandler 对象 private final TypeHandlerRegistry typeHandlerRegistry; //MappedStatement 对象,其中记录SQL 节点相应的配置信息 private final MappedStatement mappedStatement; // 用户传入的实参对象 private final Object parameterObject; // 对应的BoundSql 对象,需要设置参数的PreparedStatement 对象, 就是根据该BoundSql 中记录的SQL // 语句创建的, BoundSql 中也记录了对应参数的名称和相关属性 private final BoundSql boundSql; private final Configuration configuration; public DefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) { this.mappedStatement = mappedStatement; this.configuration = mappedStatement.getConfiguration(); this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry(); this.parameterObject = parameterObject; this.boundSql = boundSql; } @Override public Object getParameterObject() { return parameterObject; } @Override public void setParameters(PreparedStatement ps) { ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId()); // 取出sql 中的参数映射列表 List<ParameterMapping> parameterMappings = boundSql.getParameterMappings(); // 检测parameterMappings 集合是否为空 if (parameterMappings != null) { for (int i = 0; i < parameterMappings.size(); i++) { ParameterMapping parameterMapping = parameterMappings.get(i); //过滤掉存储过程中的输出参数 if (parameterMapping.getMode() != ParameterMode.OUT) { //记录绑定的实参 Object value; //获取参数名称 String propertyName = parameterMapping.getProperty(); //获取对应的实参位 if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params value = boundSql.getAdditionalParameter(propertyName); } else if (parameterObject == null) { //整个实参为空 value = null; } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) { // 实参可以直接通过TypeHandler 转换成JdbcType value = parameterObject; } else { //获取对象中相应的属性值或查找Map对象中值 MetaObject metaObject = configuration.newMetaObject(parameterObject); value = metaObject.getValue(propertyName); } //获取ParameterMapping 中设置的TypeHandler 对象 TypeHandler typeHandler = parameterMapping.getTypeHandler(); JdbcType jdbcType = parameterMapping.getJdbcType(); if (value == null && jdbcType == null) { jdbcType = configuration.getJdbcTypeForNull(); } try { //通过TypeHandler . setParametera ()方法会调用PreparedStatement.set *()方法 为SQL 语句绑定相应的实参, typeHandler.setParameter(ps, i + 1, value, jdbcType); } catch (TypeException | SQLException e) { throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e); } } } } } } SimpleStatementHandler /** * @author Clinton Begin * 它底层使用java. sql. Statement对象来完成数据库的相关操作, 所以SQL 语句中不能存在占位符, */ public class SimpleStatementHandler extends BaseStatementHandler { public SimpleStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql); } @Override public int update(Statement statement) throws SQLException { // 获取SQL 语句 String sql = boundSql.getSql(); // 获取用户传入的实参 Object parameterObject = boundSql.getParameterObject(); //获取配置的KeyGenerator 对象 KeyGenerator keyGenerator = mappedStatement.getKeyGenerator(); int rows; if (keyGenerator instanceof Jdbc3KeyGenerator) { //执行SQL 语句 statement.execute(sql, Statement.RETURN_GENERATED_KEYS); //获取受影响的行数 rows = statement.getUpdateCount(); // 将数据库生成的主键添加到parameterObject 中 keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject); } else if (keyGenerator instanceof SelectKeyGenerator) { // 执行SQL 语句 statement.execute(sql); // 获取受影响的行数 rows = statement.getUpdateCount(); // 执行< selectKey > 节点中配置的SQL 语句获取数据库生成的主键,并添加到parameterObject 中 keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject); } else { statement.execute(sql); rows = statement.getUpdateCount(); } return rows; } @Override public void batch(Statement statement) throws SQLException { String sql = boundSql.getSql(); statement.addBatch(sql); } @Override public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException { // 获取SQL 语句 String sql = boundSql.getSql(); // 调用Statement.executor ()方法执行SQL 语句 statement.execute(sql); // 映射结采集 return resultSetHandler.handleResultSets(statement); } @Override public <E> Cursor<E> queryCursor(Statement statement) throws SQLException { String sql = boundSql.getSql(); statement.execute(sql); return resultSetHandler.handleCursorResultSets(statement); } @Override protected Statement instantiateStatement(Connection connection) throws SQLException { if (mappedStatement.getResultSetType() == ResultSetType.DEFAULT) { return connection.createStatement(); } else { // 设置结果集是否可以滚动及其游标是否可以上下移动,设置结果集是否可更新 return connection.createStatement(mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY); } } @Override public void parameterize(Statement statement) { // N/A } } ## PreparedStatementHandler ## /** * @author Clinton Begin */ public class PreparedStatementHandler extends BaseStatementHandler { @Override protected Statement instantiateStatement(Connection connection) throws SQLException { //获取待执行的SQL 语句 String sql = boundSql.getSql(); // 根据MappedStatement.keyGenerator 字段的值,创建PreparedStatement 对象 if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) { String[] keyColumnNames = mappedStatement.getKeyColumns(); if (keyColumnNames == null) { // 返回数据库生成的主键 return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS); } else { // 在insert 语句执行完成之后,会将key ColumnNames 指定的列返回 return connection.prepareStatement(sql, keyColumnNames); } } else if (mappedStatement.getResultSetType() == ResultSetType.DEFAULT) { // 创建普通的PreparedSta tement 对象 return connection.prepareStatement(sql); } else { // 设置结果集是否可以滚动以及其游标是否可以上下移动,设置结果集是否可更新 return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY); } } } # Executor # public interface Executor { ResultHandler NO_RESULT_HANDLER = null; //执行update 、insert, delete 三种类型的SQL 语句 int update(MappedStatement ms, Object parameter) throws SQLException; //执行select 类型的SQL 语句,返回位分为结采对象~1]表或游标对象 <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException; <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException; <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException; //批量执行SQL 语句 List<BatchResult> flushStatements() throws SQLException; //提交事务 void commit(boolean required) throws SQLException; //回滚事务 void rollback(boolean required) throws SQLException; //创建缓存中用到的CacheKey 对象 CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql); //根据CacheKey 对象查找缓存 boolean isCached(MappedStatement ms, CacheKey key); //清空一级缓存 void clearLocalCache(); //延迟加载一级缓存中的数据 void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType); //获取事务对象 Transaction getTransaction(); //关闭E xecutor 对象 void close(boolean forceRollback); //Executor 是否已关闭 boolean isClosed(); void setExecutorWrapper(Executor executor); } ## BaseExecutor ## public abstract class BaseExecutor implements Executor { private static final Log log = LogFactory.getLog(BaseExecutor.class); // Transaction 对象,实现事务的提交、回滚和关闭操作 protected Transaction transaction; // 其中封装的Executor 对象 protected Executor wrapper; // 延迟加载队列 protected ConcurrentLinkedQueue<DeferredLoad> deferredLoads; // 一级缓存,用于缓存该Executor 对象查询结果集映射得到的结果对象 protected PerpetualCache localCache; // 一级缓存,用于缓存输出类型的参数 protected PerpetualCache localOutputParameterCache; protected Configuration configuration; //用来记录嵌套查询的层数 protected int queryStack; private boolean closed; @Override public int update(MappedStatement ms, Object parameter) throws SQLException { ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId()); //判断当前Executor 是否已经关闭 if (closed) { throw new ExecutorException("Executor was closed."); } //clearLocalCache ()方法中会调用localCache 、localOutputParameterCache 两个 //缓存的clear ()方法完成清理工作。这是影响一级缓存中数据存活时长的第三个方面 clearLocalCache(); return doUpdate(ms, parameter); } public List<BatchResult> flushStatements(boolean isRollBack) throws SQLException { if (closed) { throw new ExecutorException("Executor was closed."); } //参数isRollBack表示是否执行Executor 中缓存的SQL 语句,false 表示执行,true 表示不执行 return doFlushStatements(isRollBack); } @Override public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { //获取BoundSql 对象 BoundSql boundSql = ms.getBoundSql(parameter); // 创建CacheKey 对象 CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql); // 调用query ()的另一个重载,继续后续处理 return query(ms, parameter, rowBounds, resultHandler, key, boundSql); } @SuppressWarnings("unchecked") @Override public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId()); //检测当前Executor 是否已经关闭 if (closed) { throw new ExecutorException("Executor was closed."); } if (queryStack == 0 && ms.isFlushCacheRequired()) { //非嵌套查询,并且< select >节点配置的flushCache 属性为true 时,才会清空一级缓存 // flushCache 配置项是影响一级缓存中结果对象存活时长的第一个方面 clearLocalCache(); } List<E> list; try { //培加查询层数 queryStack++; //查询一级缓存 list = resultHandler == null ? (List<E>) localCache.getObject(key) : null; if (list != null) { //针对存储过程调用的处理, 其功能是: 在一级缓存命中时,获取缓存中保存的输出类型参数,并设置到用户传入的实参( parameter )对象中 handleLocallyCachedOutputParameters(ms, key, parameter, boundSql); } else { //其中会调用doQuery ()方法完成数据库查询,并得到映射后的结果对象 list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql); } } finally { //当前查询完成,查询层数减少 queryStack--; } if (queryStack == 0) { //延迟加载 // 在最外层的查询结束时,所有嵌套查询也已经完成,相关缓存项也已经完全加载,所以在这里可以 //触发DeferredLoad 加载一级缓存中记录的嵌套查询的结果对象 for (DeferredLoad deferredLoad : deferredLoads) { deferredLoad.load(); } // issue #601 //加裁完成后, 清空deferredLoads 集合 deferredLoads.clear(); if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) { // issue #482 //根据localCacheScope 配置决定是否清空一级缓存,localCacheScope 配置是影响一级缓 //存中结果对象存活时长的第二个方面 clearLocalCache(); } } return list; } @Override public void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType) { if (closed) { throw new ExecutorException("Executor was closed."); } // 创建DeferredLoad 对象 DeferredLoad deferredLoad = new DeferredLoad(resultObject, property, key, localCache, configuration, targetType); if (deferredLoad.canLoad()) { //一级缓存中已经记录了指定查询的结果对象, 直接从缓存中加载对象,并设置到外层对象中 deferredLoad.load(); } else { //将DeferredLoad 对象添加到deferredLoads 队列中,待整个外层查询结束后,再加载该结果对象 deferredLoads.add(new DeferredLoad(resultObject, property, key, localCache, configuration, targetType)); } } @Override public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) { //检测当前Executor 是否已经关闭 if (closed) { throw new ExecutorException("Executor was closed."); } //创建CacheKey 对象 CacheKey cacheKey = new CacheKey(); //将MappedStatement 的id 添加到Cache Key 对象中 cacheKey.update(ms.getId()); //将off set 添加到CacheKey 对象中 cacheKey.update(rowBounds.getOffset()); //将limit 添加到CacheKey 对象中 cacheKey.update(rowBounds.getLimit()); //将SQL 语句添加到CacheKey 对象中 cacheKey.update(boundSql.getSql()); List<ParameterMapping> parameterMappings = boundSql.getParameterMappings(); TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry(); // mimic DefaultParameterHandler logic //获取用户传入的实参,并添加.f1J CacheKey 对象中 for (ParameterMapping parameterMapping : parameterMappings) { //过滤输出类型的参数 if (parameterMapping.getMode() != ParameterMode.OUT) { Object value; String propertyName = parameterMapping.getProperty(); if (boundSql.hasAdditionalParameter(propertyName)) { value = boundSql.getAdditionalParameter(propertyName); } else if (parameterObject == null) { value = null; } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) { value = parameterObject; } else { MetaObject metaObject = configuration.newMetaObject(parameterObject); value = metaObject.getValue(propertyName); } //将实参添加到CacheKey 对象中 cacheKey.update(value); } } //如果Environment 的id 不为空,则将其添加到CacheKey 中 if (configuration.getEnvironment() != null) { // issue #176 cacheKey.update(configuration.getEnvironment().getId()); } return cacheKey; } @Override public boolean isCached(MappedStatement ms, CacheKey key) { //检测缓存中是否缓存了CacheKey 对应的对象 return localCache.getObject(key) != null; } @Override public void commit(boolean required) throws SQLException { if (closed) { throw new ExecutorException("Cannot commit, transaction is already closed"); } //清空一级缓存 clearLocalCache(); //执行缓存的SQL 语句,其中调用了flushStatements(false )方法 flushStatements(); //根据required 参数决定是否提交事务 if (required) { transaction.commit(); } } private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { List<E> list; // 在缓存中添加占位符 localCache.putObject(key, EXECUTION_PLACEHOLDER); try { //调用doQuery ()方法(抽象方法),完成数据库查询操作,并返回结果对象 list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql); } finally { //删除占位符 localCache.removeObject(key); } //将真正的结果对象添加到一级缓存中 localCache.putObject(key, list); //是否为存储过程调用 if (ms.getStatementType() == StatementType.CALLABLE) { //缓存输出类型的参数 localOutputParameterCache.putObject(key, parameter); } return list; } protected Connection getConnection(Log statementLog) throws SQLException { Connection connection = transaction.getConnection(); if (statementLog.isDebugEnabled()) { return ConnectionLogger.newInstance(connection, statementLog, queryStack); } else { return connection; } } @Override public void setExecutorWrapper(Executor wrapper) { this.wrapper = wrapper; } private static class DeferredLoad { //外层对象对应的MetaObject 对象 private final MetaObject resultObject; //延迟加载的属性名称 private final String property; //延迟加载的属性的类型 private final Class<?> targetType; //延迟加载的结果对象在一级缓存中相应的CacheKey 对象 private final CacheKey key; //一级缓存,与BaseExecutor.localCache 字段指向同- PerpetualCache 对象 private final PerpetualCache localCache; private final ObjectFactory objectFactory; //ResultExtractor 负责结果对象的类型转换 private final ResultExtractor resultExtractor; // issue #781 public DeferredLoad(MetaObject resultObject, String property, CacheKey key, PerpetualCache localCache, Configuration configuration, Class<?> targetType) { this.resultObject = resultObject; this.property = property; this.key = key; this.localCache = localCache; this.objectFactory = configuration.getObjectFactory(); this.resultExtractor = new ResultExtractor(configuration, objectFactory); this.targetType = targetType; } public boolean canLoad() { return //检测缓存是否存在指定的结采对象 localCache.getObject(key) != null //检测是否为占位符 && localCache.getObject(key) != EXECUTION_PLACEHOLDER; } public void load() { @SuppressWarnings("unchecked") // we suppose we get back a List //从缓存中查询指定的结采对象 List<Object> list = (List<Object>) localCache.getObject(key); //将缓存的结果对象转换成指定类型 Object value = resultExtractor.extractObjectFromList(list, targetType); // 设直到外层对象的对应属性 resultObject.setValue(property, value); } } } public class RoutingStatementHandler implements StatementHandler { //底层封装的真正的StatementHandler 对象 private final StatementHandler delegate; public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { switch (ms.getStatementType()) { case STATEMENT: delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql); break; case PREPARED: delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql); break; case CALLABLE: delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql); break; default: throw new ExecutorException("Unknown statement type: " + ms.getStatementType()); } } } ## SimpleExecutor ## /** * Copyright 2009-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.ibatis.executor; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import java.util.Collections; import java.util.List; import org.apache.ibatis.cursor.Cursor; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.logging.Log; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.RowBounds; import org.apache.ibatis.transaction.Transaction; /** * @author Clinton Begin */ public class SimpleExecutor extends BaseExecutor { public SimpleExecutor(Configuration configuration, Transaction transaction) { super(configuration, transaction); } @Override public int doUpdate(MappedStatement ms, Object parameter) throws SQLException { Statement stmt = null; try { Configuration configuration = ms.getConfiguration(); StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null); stmt = prepareStatement(handler, ms.getStatementLog()); return handler.update(stmt); } finally { closeStatement(stmt); } } @Override public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { Statement stmt = null; try { //获取配置对象 Configuration configuration = ms.getConfiguration(); // 创建StatementHandler 对象,实际返回的是RoutingStatementHandler 对象, StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql); //完成Statement 的创建和初始化,该方法首先会调用StatementHandler.prepare ()方法创建 //Statement 对象, 然后调用StatementH andler. parameterize ()方法处理占位符 stmt = prepareStatement(handler, ms.getStatementLog()); //调用StatementHandler.query ()方法,执行SQL 语句,并通过ResultSetHandler 完成结果集的映射 return handler.query(stmt, resultHandler); } finally { //关闭Statement对象 closeStatement(stmt); } } @Override protected <E> Cursor<E> doQueryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql) throws SQLException { Configuration configuration = ms.getConfiguration(); StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, null, boundSql); Statement stmt = prepareStatement(handler, ms.getStatementLog()); Cursor<E> cursor = handler.queryCursor(stmt); stmt.closeOnCompletion(); return cursor; } @Override public List<BatchResult> doFlushStatements(boolean isRollback) { return Collections.emptyList(); } private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException { Statement stmt; Connection connection = getConnection(statementLog); //创建Statement 对象 stmt = handler.prepare(connection, transaction.getTimeout()); //处理占位符 handler.parameterize(stmt); return stmt; } } ## ReuseExecutor ## /** * @author Clinton Begin * 尝试重用StaternentMap 中缓存的Statement 对象。 */ public class ReuseExecutor extends BaseExecutor { @Override public List<BatchResult> doFlushStatements(boolean isRollback) { for (Statement stmt : statementMap.values()) { //遍历staternentMap 集合并关闭其中的Statement 对象 closeStatement(stmt); } //清空staternentMap 缓存 statementMap.clear(); //返回空集合 return Collections.emptyList(); } private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException { Statement stmt; BoundSql boundSql = handler.getBoundSql(); //获取SQL 语句 String sql = boundSql.getSql(); //检测是否缓存了相同模式的SQL 语句所对应的Statement 对象 if (hasStatementFor(sql)) { //获取statementMap 集合中缓存的Statement 对象 stmt = getStatement(sql); //修改超时时间 applyTransactionTimeout(stmt); } else { //获取数据库连接 Connection connection = getConnection(statementLog); //创建新的Statement 对象,并缓存到staternentMap 集合中 stmt = handler.prepare(connection, transaction.getTimeout()); putStatement(sql, stmt); } //处理占位符 handler.parameterize(stmt); return stmt; } } ## BatchExecutor ## public class BatchExecutor extends BaseExecutor { public static final int BATCH_UPDATE_RETURN_VALUE = Integer.MIN_VALUE + 1002; //缓存多个Statement 对象其中每个Statement 对象中都缓存了多条SQL 语句 private final List<Statement> statementList = new ArrayList<>(); //记录批处理的结果 private final List<BatchResult> batchResultList = new ArrayList<>(); // 记录当前执行的S QL 语句 private String currentSql; //记录当前执行的MappedStatement 对象 private MappedStatement currentStatement; public BatchExecutor(Configuration configuration, Transaction transaction) { super(configuration, transaction); } @Override public int doUpdate(MappedStatement ms, Object parameterObject) throws SQLException { //获取配置对象 final Configuration configuration = ms.getConfiguration(); //创建StatementHandler 对象 final StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, RowBounds.DEFAULT, null, null); final BoundSql boundSql = handler.getBoundSql(); //获取SQL 语句 final String sql = boundSql.getSql(); final Statement stmt; //如果当前执行的SQL 模式与上次执行的SQL 模式相同且对应的MappedStatement 对象相同 if (sql.equals(currentSql) && ms.equals(currentStatement)) { //获取statementList 集合中最后一个Statement 对象 int last = statementList.size() - 1; stmt = statementList.get(last); applyTransactionTimeout(stmt); //绑定实参, 处理” ? ” 占位符 handler.parameterize(stmt);// fix Issues 322 //查找对应的BatchResult 对象,并记录用户传入的实参 BatchResult batchResult = batchResultList.get(last); batchResult.addParameterObject(parameterObject); } else { Connection connection = getConnection(ms.getStatementLog()); //创建新的Statement 对象 stmt = handler.prepare(connection, transaction.getTimeout()); //绑定实参,处理” ? ”占位符 handler.parameterize(stmt); // fix Issues 322 //更新currentSql 和currentStatement currentSql = sql; currentStatement = ms; //将新创建的Statement 对象添加到statementList 集合中 statementList.add(stmt); //添加新的BatchResult 对象 batchResultList.add(new BatchResult(ms, sql, parameterObject)); } //底层通过调用Statement.addBatch ()方法添加SQL 语句 handler.batch(stmt); return BATCH_UPDATE_RETURN_VALUE; } @Override public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException { try { // results 集合用于储存批处理的结果 List<BatchResult> results = new ArrayList<>(); //如果明确指定了要回滚事务,则直接返回空集合,忽略statementList 集合中记录的SQL 语句 if (isRollback) { return Collections.emptyList(); } //遥历statementList 集合 for (int i = 0, n = statementList.size(); i < n; i++) { // 获取Statement 对象 Statement stmt = statementList.get(i); applyTransactionTimeout(stmt); //获取对应BatchResult 对象 BatchResult batchResult = batchResultList.get(i); try { // 调用Statement.executeBatch ()方法批量执行其中记录的SQL 语句,并使用返回的int数组 // 更新BatchResult.updateCounts 字段,其中每一个元素都表示一条SQL 语句影响的记录条数 batchResult.setUpdateCounts(stmt.executeBatch()); MappedStatement ms = batchResult.getMappedStatement(); List<Object> parameterObjects = batchResult.getParameterObjects(); //获取配置的KeyGenerator 对象 KeyGenerator keyGenerator = ms.getKeyGenerator(); if (Jdbc3KeyGenerator.class.equals(keyGenerator.getClass())) { Jdbc3KeyGenerator jdbc3KeyGenerator = (Jdbc3KeyGenerator) keyGenerator; //获取数据库生成的主键,并设置到parameterObjects 中 jdbc3KeyGenerator.processBatch(ms, stmt, parameterObjects); } else if (!NoKeyGenerator.class.equals(keyGenerator.getClass())) { //issue #141 //对于其他类型的KeyGenerator ,会调用其processAfter ()方法 for (Object parameter : parameterObjects) { keyGenerator.processAfter(this, ms, stmt, parameter); } } // Close statement to close cursor #1109 closeStatement(stmt); } catch (BatchUpdateException e) { StringBuilder message = new StringBuilder(); message.append(batchResult.getMappedStatement().getId()) .append(" (batch index #") .append(i + 1) .append(")") .append(" failed."); if (i > 0) { message.append(" ") .append(i) .append(" prior sub executor(s) completed successfully, but will be rolled back."); } throw new BatchExecutorException(message.toString(), e, results, batchResult); } //添加BatchResult 到results 集合 results.add(batchResult); } return results; } finally { for (Statement stmt : statementList) { //关闭所有Statement 对象,并清空current Sql 字段、清空statement List 集合、清空batchResultList 集合 closeStatement(stmt); } currentSql = null; statementList.clear(); batchResultList.clear(); } } } ## CachingExecutor ## /** * @author Clinton Begin * @author Eduardo Macarron * 为指定的命名空间创建相应的Cache 对象作为 * 其二级缓存,默认是PerpetualCache 对象 */ public class CachingExecutor implements Executor { @Override public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { //步骤1 :获取BoundSql 对象, BoundSql boundSql = ms.getBoundSql(parameterObject); //创建CacheKey 对象 CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql); return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); } @Override public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { //获取查询语句所在命名空间对应的二级缓存 Cache cache = ms.getCache(); //步骤2 :是否开启了二级缓存功能 if (cache != null) { // 根据< select >节点的配置,决定是否需妥清空二级缓存 flushCacheIfRequired(ms); //检测SQL 节点的useCache 配置以及是否使用了resultHandler 配置 if (ms.isUseCache() && resultHandler == null) { //步骤3 :二级缓存不能保存输出类型的参数, 如果查询操作调用了包含输出参数的存储过程,则报错 ensureNoOutParams(ms, boundSql); @SuppressWarnings("unchecked") //步骤4 :查询二级缓存 List<E> list = (List<E>) tcm.getObject(cache, key); if (list == null) { //步骤5 :二级缓存没有相应的结采对象,调用封装的Executor 对象的query ()方法,其中会允查询一级缓存 list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); //将查询结果保存到TransactionalCache.entriesToAddOnCornrnit 集合中 tcm.putObject(cache, key, list); // issue #578 and #116 } return list; } } //没有启动二级缓存,直接调用底层Exe cutor 执行数据库查询操作 return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); } @Override public void commit(boolean required) throws SQLException { // 调用底层的Executor 提交事务 delegate.commit(required); //边历所有相关的TransactionalCache 对象执行commit ()方法 tcm.commit(); } @Override public void rollback(boolean required) throws SQLException { try { //调用底层的Executor 回滚事务 delegate.rollback(required); } finally { if (required) { //遍历所有相关的TransactionalCache 对象执行rollback ()方法 tcm.rollback(); } } } } ## TransactionalCache ## public class TransactionalCache implements Cache { private static final Log log = LogFactory.getLog(TransactionalCache.class); // 底层封装的二级缓存所对应的Cache 对象 private final Cache delegate; //当该字段为true 时,则表示当前TransactionalCache 不可查询, 且提交事务时会将底层Cache 清空 private boolean clearOnCommit; // 暂时记录添加到TransactionalCache 中的数据。在事务提交时,会将其中的数据添加到二级後存中 private final Map<Object, Object> entriesToAddOnCommit; // 记录缓存未命中的CacheKey 对象 private final Set<Object> entriesMissedInCache; public TransactionalCache(Cache delegate) { this.delegate = delegate; this.clearOnCommit = false; this.entriesToAddOnCommit = new HashMap<>(); this.entriesMissedInCache = new HashSet<>(); } @Override public String getId() { return delegate.getId(); } @Override public int getSize() { return delegate.getSize(); } @Override public Object getObject(Object key) { // issue #116 //查询底层的Cache 是否包含指定的key Object object = delegate.getObject(key); if (object == null) { //如果底层缓存对象中不包含该缓存项, 则将该key 记录到entriesMissedInCache集合中 entriesMissedInCache.add(key); } // issue #146 //如果clearOnCommit 为true ,则当前TransactionalCache 不可查询,始终返回null if (clearOnCommit) { return null; } else { //返回从底层Cache 中查询到的对象 return object; } } @Override public void putObject(Object key, Object object) { // 将缓存项暂存在entriesToAddOnCommit 集合中 entriesToAddOnCommit.put(key, object); } @Override public Object removeObject(Object key) { return null; } @Override public void clear() { clearOnCommit = true; entriesToAddOnCommit.clear(); } public void commit() { //在事务提交前, 清空二级缓存 if (clearOnCommit) { delegate.clear(); } //将entriesToAddOnCommit 集合中的数据保存到二级缓存 flushPendingEntries(); //重置clearOnCommit 为false ,并清空entriesToAddOnCommit 、entriesMissedinCache 集合 reset(); } public void rollback() { //将entriesMissedinCache 集合中记录的缓存项从二级缓存中删除 unlockMissedEntries(); //重置clearOnCommit 为false ,并清空entriesToAddOnCommit 、entriesMissedinCache 集合 reset(); } private void reset() { clearOnCommit = false; entriesToAddOnCommit.clear(); entriesMissedInCache.clear(); } private void flushPendingEntries() { //遍历entriesToAddOnCommit 集合,将其中记录的缓存项添加到二级缓存中 for (Map.Entry<Object, Object> entry : entriesToAddOnCommit.entrySet()) { delegate.putObject(entry.getKey(), entry.getValue()); } //遍历entriesMissedinCache 集合,将entriesToAddOnCommit 集合中不包含的缓存项添加到 二级缓存中 for (Object entry : entriesMissedInCache) { if (!entriesToAddOnCommit.containsKey(entry)) { delegate.putObject(entry, null); } } } private void unlockMissedEntries() { for (Object entry : entriesMissedInCache) { try { delegate.removeObject(entry); } catch (Exception e) { log.warn("Unexpected exception while notifiying a rollback to the cache adapter. " + "Consider upgrading your cache adapter to the latest version. Cause: " + e); } } } } # SqlSession # ## DefaultSqlSession ## public class DefaultSqlSession implements SqlSession { //configuration 配置对象 private final Configuration configuration; //底层依赖的Executor 对象 private final Executor executor; //是否自动提交事务 private final boolean autoCommit; //当前缓存中是否有脏数据 private boolean dirty; //为防止用户忘记关闭已打开的游标对象,会通过cursorList 字段记录由该SqlSession 对象生成的游标 //对象,在DefaultSqlSession.close ()方法中会统一关闭这些游标对象 private List<Cursor<?>> cursorList; } ## DefaultSqlSessionFactory ## public class DefaultSqlSessionFactory implements SqlSessionFactory { /** * 通过数据源获取数据库连接, 并创建Executor 对象以及DefaultSqlSession 对象 * @param execType * @param level * @param autoCommit * @return */ private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx = null; try { //获取mybatis-config.xml 配置文件中配置的Environment 对象 final Environment environment = configuration.getEnvironment(); //获取的TransactionFactory 对象 final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); //创建Transaction 对象 tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); //根据配置创建Executor 对象 final Executor executor = configuration.newExecutor(tx, execType); //创建DefaultSqlSession 对象 return new DefaultSqlSession(configuration, executor, autoCommit); } catch (Exception e) { // 关闭Transaction closeTransaction(tx); // may have fetched a connection so lets call close() throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } } /** * 用户提供数据库连接对象, DefaultSqlSessionFactory * 会使用该数据库连接对象创建Executor 对象以及DefaultSqlSession 对象 * @param execType * @param connection * @return */ private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) { try { boolean autoCommit; try { //获取当前连接的事务是否为自动提交方式 autoCommit = connection.getAutoCommit(); } catch (SQLException e) { // Failover to true, as most poor drivers // or databases won't support transactions //当前数据库驱动提供的连接不支持事务,则可能会抛出异常 autoCommit = true; } //获取mybatis config. xml 配置文件中配置的E nv 工ronment 对象 final Environment environment = configuration.getEnvironment(); //获取的TransactionFactory 对象 final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); //创建Transaction 对象 final Transaction tx = transactionFactory.newTransaction(connection); //根据配置创建Executor 对象 final Executor executor = configuration.newExecutor(tx, execType); //创建DefaultSqlSession 对象 return new DefaultSqlSession(configuration, executor, autoCommit); } catch (Exception e) { throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } } } ## SqlSessionManager ## public class SqlSessionManager implements SqlSessionFactory, SqlSession { //底层封装的SqlSessionFactory 对象 private final SqlSessionFactory sqlSessionFactory; // localSqlSession 中记录的SqlSession 对象的代理对象,在sqlSessionManager初始化时, //会使用JDK 动态代理的方式为localSqlSession创建代理对象 private final SqlSession sqlSessionProxy; // ThreadLocal 变量,记录一个与当前线程绑定的SqlSession 对象 private final ThreadLocal<SqlSession> localSqlSession = new ThreadLocal<>(); private SqlSessionManager(SqlSessionFactory sqlSessionFactory) { this.sqlSessionFactory = sqlSessionFactory; //使用动态代理的方式生成Sql Session 的代理对象 this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance( SqlSessionFactory.class.getClassLoader(), new Class[]{ SqlSession.class}, new SqlSessionInterceptor()); } //通过newinstance()方法创建SqlSessionManager 对象 public static SqlSessionManager newInstance(Reader reader) { return new SqlSessionManager(new SqlSessionFactoryBuilder().build(reader, null, null)); } private class SqlSessionInterceptor implements InvocationHandler { public SqlSessionInterceptor() { // Prevent Synthetic Access } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //获取当前线程绑定的SqlSession 对象 final SqlSession sqlSession = SqlSessionManager.this.localSqlSession.get(); if (sqlSession != null) { try { //调用真正的SqlSession 对象,完成数据库的相关操作 return method.invoke(sqlSession, args); } catch (Throwable t) { throw ExceptionUtil.unwrapThrowable(t); } } else { //如果当前线程未绑定SqlSession 对象,则创建新的SqlSession 对象 try (SqlSession autoSqlSession = openSession()) { try { //通过新建的SqlSession 对象完成数据库操作 final Object result = method.invoke(autoSqlSession, args); // 提交事务 autoSqlSession.commit(); return result; } catch (Throwable t) { //回滚事务 autoSqlSession.rollback(); throw ExceptionUtil.unwrapThrowable(t); } } } } } }
还没有评论,来说两句吧...