Demo 主启动类 javapublicclassMybatisHelloWorld{publicstaticvoidmain(String〔〕args)throwsException{Stringresourceorgmybatisconfig。xml;InputStreaminputStreamResources。getResourceAsStream(resource);SqlSessionFactorysqlSessionFactorynewSqlSessionFactoryBuilder()。build(inputStream);SqlSessionsessionsqlSessionFactory。openSession();UserMappermappersession。getMapper(UserMapper。class);ListUserusersmapper。getUsers(1);session。close();}} userMapper。class javapublicinterfaceUserMapper{Select({selectfromuserwhereage{age}})ListUsergetUsers(intage);} config。xml xmllt;?xmlversion1。0encodingUTF8?!DOCTYPEconfigurationPUBLICmybatis。orgDTDConfig3。0ENhttp:mybatis。orgdtdmybatis3config。dtdconfigurationsettings控制台输出sqlsettingnamelogImplvalueSTDOUTLOGGINGsettingsenvironmentsdefaultdevelopmentenvironmentiddevelopmenttransactionManagertypeJDBCdataSourcetypePOOLEDpropertynamedrivervaluecom。mysql。jdbc。Driverpropertynameurlvaluejdbc:mysql:localhost:3306mybatis?serverTimezoneUTCpropertynameusernamevaluerootpropertynamepasswordvaluerootdataSourceenvironmentenvironmentsmapperspackagenameorg。mybatis。mappermappersconfiguration Mybatis通过session来进行数据库的操作,sqlSessionFactory封装了session的创建,而SqlSessionFactoryBuilder又封装了sqlSessionFactory的创建 从上面代码来看总共做了两件事读取配置文件,通过SqlSessionFactoryBuilder创建sqlSessionFactory继而创建session获取mapper进行读取数据库 先来看如何将xml配置文件封装为对象的解析配置文件 javanewSqlSessionFactoryBuilder()。build(inputStream); 这里使用构造者模式来创建一个sqlSessionFactory,里面使用重载 javapublicSqlSessionFactorybuild(InputStreaminputStream){returnbuild(inputStream,null,null);} 最终调用 SqlSessionFactoryBuilder。java javapublicSqlSessionFactorybuild(InputStreaminputStream,Stringenvironment,Propertiesproperties){try{创建一个xml解析类XMLConfigBuilderparsernewXMLConfigBuilder(inputStream,environment,properties);解析xml中配置,转换为configuration类returnbuild(parser。parse());}catch(Exceptione){throwExceptionFactory。wrapException(ErrorbuildingSqlSession。,e);}finally{ErrorContext。instance()。reset();try{inputStream。close();}catch(IOExceptione){Intentionallyignore。Preferpreviouserror。}}} mybatis是把一些配置类以及它自己需要使用的各种类封装成一个大的config对象 org。apache。ibatis。session。Configuration里面有很多环境,mapper等等的信息,内容太多就不粘贴了 XMLConfigBuilder。java javapublicXMLConfigBuilder(InputStreaminputStream,Stringenvironment,Propertiesprops){this(newXPathParser(inputStream,true,props,newXMLMapperEntityResolver()),environment,props);}privateXMLConfigBuilder(XPathParserparser,Stringenvironment,Propertiesprops){创建了一个Configuration对象super(newConfiguration());ErrorContext。instance()。resource(SQLMapperConfiguration);this。configuration。setVariables(props);this。parsedfalse;这一行设置环境idthis。environmentenvironment;this。parserparser;} XMlConfigBuilder类关系图 BaseBuilder。java javapublicBaseBuilder(Configurationconfiguration){this。configurationconfiguration;this。typeAliasRegistrythis。configuration。getTypeAliasRegistry();this。typeHandlerRegistrythis。configuration。getTypeHandlerRegistry();} 解析主配置文件。xml SqlSessionFactoryBuilder。java javapublicSqlSessionFactorybuild(InputStreaminputStream,Stringenvironment,Propertiesproperties){。。。。returnbuild(parser。parse());。。。。}publicConfigurationparse(){if(parsed){thrownewBuilderException(EachXMLConfigBuildercanonlybeusedonce。);}parsedtrue;读取configuration节点下的node传入parseConfiguration(parser。evalNode(configuration));returnconfiguration;}privatevoidparseConfiguration(XNoderoot){try{issue117readpropertiesfirst读取propertiespropertiesElement(root。evalNode(properties));读取一些setting设置PropertiessettingssettingsAsProperties(root。evalNode(settings));loadCustomVfs(settings);注册别名typeAliasesElement(root。evalNode(typeAliases));插件,进行增强先略过pluginElement(root。evalNode(plugins));对象工厂,自定义实例化方法略过objectFactoryElement(root。evalNode(objectFactory));objectWrapperFactoryElement(root。evalNode(objectWrapperFactory));reflectionFactoryElement(root。evalNode(reflectionFactory));settingsElement(settings);readitafterobjectFactoryandobjectWrapperFactoryissue631配置环境environmentsElement(root。evalNode(environments));数据厂商表示略过databaseIdProviderElement(root。evalNode(databaseIdProvider));typeHandlerElement(root。evalNode(typeHandlers));配置mappermapperElement(root。evalNode(mappers));}catch(Exceptione){thrownewBuilderException(ErrorparsingSQLMapperConfiguration。Cause:e,e);}} 解析的东西很多,我们只先看environments和mapperenvironmentsElement XMLConfigBuilder。java javaprivatevoidenvironmentsElement(XNodecontext)throwsException{if(context!null){if(environmentnull){environmentcontext。getStringAttribute(default);}for(XNodechild:context。getChildren()){Stringidchild。getStringAttribute(id);可以配置多个环境,判断是不是指定的环境if(isSpecifiedEnvironment(id)){获取事物管理器,创建事物管理器工厂TransactionFactorytxFactorytransactionManagerElement(child。evalNode(transactionManager));获取datasource工厂UnpooledDataSourceFactory默认DataSourceFactorydsFactorydataSourceElement(child。evalNode(dataSource));DataSourcedataSourcedsFactory。getDataSource();Environment。BuilderenvironmentBuildernewEnvironment。Builder(id)。transactionFactory(txFactory)。dataSource(dataSource);configuration。setEnvironment(environmentBuilder。build());}}}} 进入发现第一件是就是判断环境,没有指定就使用中default的环境id,在上面的XMLConfigBuilder的有参构造中this。environmentenvironment;将环境配置设置给了XMLConfigBuilder的environment点我跳转到XMLConfigBuilder有参构造 我们在使用时可以这样,在配置文件xml中,声明多个环境 xmlenvironmentsdefaultdevelopmentenvironmentiddevelopmenttransactionManagertypeJDBCdataSourcetypePOOLEDpropertynamedrivervaluecom。mysql。jdbc。Driverpropertynameurlvaluejdbc:mysql:localhost:3306mybatis?serverTimezoneUTCpropertynameusernamevaluerootpropertynamepasswordvaluerootdataSourceenvironmentenvironmentidmyTesttransactionManagertypeJDBCdataSourcetypePOOLEDpropertynamedrivervaluecom。mysql。jdbc。Driverpropertynameurlvaluejdbc:mysql:localhost:3306mybatis?serverTimezoneUTCpropertynameusernamevaluerootpropertynamepasswordvaluerootdataSourceenvironmentenvironments 主启动类中,手动指明一个配置环境 javapublicstaticvoidmain(String〔〕args)throwsException{。。。。SqlSessionFactorysqlSessionFactorynewSqlSessionFactoryBuilder()。build(inputStream,myTest);。。。。} 回到代码第一步就是判断用户选择的那个id的环境,之后创建事务管理器 XMLConfigBuilder。java javaprivatevoidenvironmentsElement(XNodecontext)throwsException{。。TransactionFactorytxFactorytransactionManagerElement(child。evalNode(transactionManager));。。}privateTransactionFactorytransactionManagerElement(XNodecontext)throwsException{if(context!null){获取我们在xml中声明的事务管理类型,当前是JDBCStringtypecontext。getStringAttribute(type);获取节点下的子节点,当前案例没有子节点Propertiespropscontext。getChildrenAsProperties();这里只是创建工厂类TransactionFactoryfactory(TransactionFactory)resolveClass(type)。newInstance();factory。setProperties(props);returnfactory;}thrownewBuilderException(EnvironmentdeclarationrequiresaTransactionFactory。);} 这里调用resolveClass()方法是父类BaseBuilder的方法 一直点进去最后如下 TypeAliasRegistry。java javapublicclassTypeAliasRegistry{privatefinalMapString,Classlt;?TYPEALIASESnewHashMapString,Classlt;?();。。。。。publicTClassTresolveAlias(Stringstring){try{if(stringnull){returnnull;}issue748Stringkeystring。toLowerCase(Locale。ENGLISH);ClassTvalue;if(TYPEALIASES。containsKey(key)){value(ClassT)TYPEALIASES。get(key);}else{value(ClassT)Resources。classForName(string);}returnvalue;}catch(ClassNotFoundExceptione){thrownewTypeException(Couldnotresolvetypealiasstring。Cause:e,e);}}} 判断这个TYPEALIASESmap中是否存在JDBC这个key,如果不存在,则去加载 按理来说这里应该是不存在的,因为你在TypeAliasRegistry中找不到任何一个地方对TYPEALIASES添加一个JDBC的key 但是实际它却存在这个key,在Configuration类的无参构造时,对这个TypeAliasRegistry进行的添加 Configuration。java javapublicConfiguration(){typeAliasRegistry。registerAlias(JDBC,JdbcTransactionFactory。class);。。。typeAliasRegistry。registerAlias(POOLED,PooledDataSourceFactory。class);languageRegistry。setDefaultDriverClass(XMLLanguageDriver。class);。。。。。。} 这个过程如下图 回到代码因为我们这次案例的配置为所以不会存在子节点context。getChildrenAsProperties();返回的结果0个配置项,transactionManagerElement方法结束 之后去解析数据库配置文件 XMLConfigBulider。java javaprivatevoidenvironmentsElement(XNodecontext)throwsException{。。。获取datasource工厂UnpooledDataSourceFactory默认DataSourceFactorydsFactorydataSourceElement(child。evalNode(dataSource));DataSourcedataSourcedsFactory。getDataSource();。。。} 和解析环境基本一样的代码,不过解析dataSource的时候,子节点就不为空了 会有四个属性 xmldataSourcetypePOOLEDpropertynamedrivervaluecom。mysql。jdbc。Driverpropertynameurlvaluejdbc:mysql:localhost:3306mybatis?serverTimezoneUTCpropertynameusernamevalueroot222propertynamepasswordvalueroot222dataSource javaprivateDataSourceFactorydataSourceElement(XNodecontext)throwsException{if(context!null){Stringtypecontext。getStringAttribute(type);Propertiespropscontext。getChildrenAsProperties();type为POOLED的默认实现是PooledDataSourceFactoryDataSourceFactoryfactory(DataSourceFactory)resolveClass(type)。newInstance();factory。setProperties(props);returnfactory;}thrownewBuilderException(EnvironmentdeclarationrequiresaDataSourceFactory。);} 进入factory。setProperties(props); javapublicclassUnpooledDataSourceFactoryimplementsDataSourceFactory{privatestaticfinalStringDRIVERPROPERTYPREFIXdriver。;privatestaticfinalintDRIVERPROPERTYPREFIXLENGTHDRIVERPROPERTYPREFIX。length();protectedDataSourcedataSource;无参默认将dataSource设置为UnpooledDataSourcepublicUnpooledDataSourceFactory(){this。dataSourcenewUnpooledDataSource();}OverridepublicvoidsetProperties(Propertiesproperties){PropertiesdriverPropertiesnewProperties();将工厂对象进行包装MetaObjectmetaDataSourceSystemMetaObject。forObject(dataSource);for(Objectkey:properties。keySet()){StringpropertyName(String)key;如果存在driverif(propertyName。startsWith(DRIVERPROPERTYPREFIX)){Stringvalueproperties。getProperty(propertyName);driverProperties。setProperty(propertyName。substring(DRIVERPROPERTYPREFIXLENGTH),value);如果当前属性在类中有对应的可以写入的属性}elseif(metaDataSource。hasSetter(propertyName)){Stringvalue(String)properties。get(propertyName);ObjectconvertedValueconvertValue(metaDataSource,propertyName,value);metaDataSource。setValue(propertyName,convertedValue);}else{thrownewDataSourceException(UnknownDataSourceproperty:propertyName);}}如果属性不为空,则设置给meatDataSourceif(driverProperties。size()0){metaDataSource。setValue(driverProperties,driverProperties);}}。。。。。。} 一顿设置后回到XMLConfigurationBuilder中的environmentsElement方法 最后将读取出的配置封装为Environment,赋值给BaseBuilder中的environment javaprivatevoidenvironmentsElement(XNodecontext)throwsException{。。。。。DataSourceFactorydsFactorydataSourceElement(child。evalNode(dataSource));DataSourcedataSourcedsFactory。getDataSource();Environment。BuilderenvironmentBuildernewEnvironment。Builder(id)。transactionFactory(txFactory)。dataSource(dataSource);configuration。setEnvironment(environmentBuilder。build());。。。。。}mapperElement 回到XMLConfigBuilder中的parseConfiguration javaprivatevoidparseConfiguration(XNoderoot){。。。。。配置mappermapperElement(root。evalNode(mappers));} 我们只看根据包扫描的,给Configuration中添加了mapper包名 javaprivatevoidmapperElement(XNodeparent)throwsException{if(parent!null){for(XNodechild:parent。getChildren()){使用包,默认查找指定包下位置if(package。equals(child。getName())){StringmapperPackagechild。getStringAttribute(name);configuration。addMappers(mapperPackage);}。。。。。}}} Configuration。java javapublicvoidaddMappers(StringpackageName){mapperRegistry。addMappers(packageName);} MapperRegistry。java javapublicvoidaddMappers(StringpackageName){addMappers(packageName,Object。class);}根据包名去查询该包下的类publicvoidaddMappers(StringpackageName,Classlt;?superType){ResolverUtilClasslt;?resolverUtilnewResolverUtilClasslt;?();resolverUtil。find(newResolverUtil。IsA(superType),packageName);SetClasslt;?extendsClasslt;?mapperSetresolverUtil。getClasses();for(Classlt;?mapperClass:mapperSet){addMapper(mapperClass);}} 之后就是动态代理对应的mapper MapperRegistry。java javapublicTvoidaddMapper(ClassTtype){if(type。isInterface()){判断是否已经存在if(hasMapper(type)){thrownewBindingException(TypetypeisalreadyknowntotheMapperRegistry。);}booleanloadCompletedfalse;try{knownMappers。put(type,newMapperProxyFactoryT(type));MapperAnnotationBuilderparsernewMapperAnnotationBuilder(config,type);parser。parse();loadCompletedtrue;}finally{if(!loadCompleted){knownMappers。remove(type);}}}} javapublicclassMapperProxyFactoryT{privatefinalClassTmapperInterface;privatefinalMapMethod,MapperMethodmethodCachenewConcurrentHashMapMethod,MapperMethod();publicMapperProxyFactory(ClassTmapperInterface){this。mapperInterfacemapperInterface;}publicClassTgetMapperInterface(){returnmapperInterface;}publicMapMethod,MapperMethodgetMethodCache(){returnmethodCache;}SuppressWarnings(unchecked)protectedTnewInstance(MapperProxyTmapperProxy){return(T)Proxy。newProxyInstance(mapperInterface。getClassLoader(),newClass〔〕{mapperInterface},mapperProxy);}publicTnewInstance(SqlSessionsqlSession){finalMapperProxyTmapperProxynewMapperProxyT(sqlSession,mapperInterface,methodCache);returnnewInstance(mapperProxy);}} 主要来看这段 javaMapperAnnotationBuilderparsernewMapperAnnotationBuilder(config,type);parser。parse(); MapperAnnotationBuilder。java javapublicclassMapperAnnotationBuilder{privatefinalSetClasslt;?extendsAnnotationsqlAnnotationTypesnewHashSetClasslt;?extendsAnnotation();privatefinalSetClasslt;?extendsAnnotationsqlProviderAnnotationTypesnewHashSetClasslt;?extendsAnnotation();。。。。在构造时添加mybatis的注解publicMapperAnnotationBuilder(Configurationconfiguration,Classlt;?type){Stringresourcetype。getName()。replace(。,)。java(bestguess);this。assistantnewMapperBuilderAssistant(configuration,resource);this。configurationconfiguration;this。typetype;sqlAnnotationTypes。add(Select。class);sqlAnnotationTypes。add(Insert。class);sqlAnnotationTypes。add(Update。class);sqlAnnotationTypes。add(Delete。class);sqlProviderAnnotationTypes。add(SelectProvider。class);sqlProviderAnnotationTypes。add(InsertProvider。class);sqlProviderAnnotationTypes。add(UpdateProvider。class);sqlProviderAnnotationTypes。add(DeleteProvider。class);}publicvoidparse(){Stringresourcetype。toString();if(!configuration。isResourceLoaded(resource)){loadXmlResource();configuration。addLoadedResource(resource);assistant。setCurrentNamespace(type。getName());parseCache();parseCacheRef();Method〔〕methodstype。getMethods();for(Methodmethod:methods){try{issue237if(!method。isBridge()){parseStatement(method);}}catch(IncompleteElementExceptione){configuration。addIncompleteMethod(newMethodResolver(this,method));}}}parsePendingMethods();}} javavoidparseStatement(Methodmethod){Classlt;?parameterTypeClassgetParameterType(method);LanguageDriverlanguageDrivergetLanguageDriver(method);SqlSourcesqlSourcegetSqlSourceFromAnnotations(method,parameterTypeClass,languageDriver);。。。} 首先第一步是获取参数类型代码如下,如果mapper的入参数量大于1,则返回的就是ParamMap。class javaprivateClasslt;?getParameterType(Methodmethod){Classlt;?parameterTypenull;Classlt;?〔〕parameterTypesmethod。getParameterTypes();for(inti0;iparameterTypes。length;i){if(!RowBounds。class。isAssignableFrom(parameterTypes〔i〕)!ResultHandler。class。isAssignableFrom(parameterTypes〔i〕)){if(parameterTypenull){parameterTypeparameterTypes〔i〕;}else{issue135parameterTypeParamMap。class;}}}returnparameterType;} 之后获取语言解析,没有指定就去找默认默认的是XMLLanguageDriver。class还是在Configuration类无参构造时添加进去的点我跳转到Configuration无参构造 javaprivateLanguageDrivergetLanguageDriver(Methodmethod){Langlangmethod。getAnnotation(Lang。class);Classlt;?langClassnull;if(lang!null){langClasslang。value();}returnassistant。getLanguageDriver(langClass);} 获取注解上的内容,以及封装sql就在这个方法 javaprivateSqlSourcegetSqlSourceFromAnnotations(Methodmethod,Classlt;?parameterType,LanguageDriverlanguageDriver){try{获取是否存在Select,Insert。。。。Classlt;?extendsAnnotationsqlAnnotationTypegetSqlAnnotationType(method);获取是否存在SelectProvider,InsertProvider。。。Classlt;?extendsAnnotationsqlProviderAnnotationTypegetSqlProviderAnnotationType(method);if(sqlAnnotationType!null){if(sqlProviderAnnotationType!null){thrownewBindingException(YoucannotsupplybothastaticSQLandSqlProvidertomethodnamedmethod。getName());}AnnotationsqlAnnotationmethod。getAnnotation(sqlAnnotationType);获取注解上的值finalString〔〕strings(String〔〕)sqlAnnotation。getClass()。getMethod(value)。invoke(sqlAnnotation);返回sqlSource这个时候还没有进行填充值returnbuildSqlSourceFromStrings(strings,parameterType,languageDriver);}elseif(sqlProviderAnnotationType!null){AnnotationsqlProviderAnnotationmethod。getAnnotation(sqlProviderAnnotationType);returnnewProviderSqlSource(assistant。getConfiguration(),sqlProviderAnnotation);}returnnull;}catch(Exceptione){thrownewBuilderException(CouldnotfindvaluemethodonSQLannotation。Cause:e,e);}} 此时的strings值还是selectfromuserwhereage{age}需要给替换为selectfromuserwhereage? javaprivateSqlSourcebuildSqlSourceFromStrings(String〔〕strings,Classlt;?parameterTypeClass,LanguageDriverlanguageDriver){finalStringBuildersqlnewStringBuilder();for(Stringfragment:strings){sql。append(fragment);sql。append();}returnlanguageDriver。createSqlSource(configuration,sql。toString()。trim(),parameterTypeClass);} 默认的语言驱动是XMLLanguageDriver XMLLanguageDriver。java 首先判断注解上的内容是否存在脚本,在mybatis官网,动态SQL下的script有使用案例,使得在注解中可以像在xml中使用ifwhere等标签 javaOverridepublicSqlSourcecreateSqlSource(Configurationconfiguration,Stringscript,Classlt;?parameterType){issue3if(script。startsWith(lt;script)){XPathParserparsernewXPathParser(script,false,configuration。getVariables(),newXMLMapperEntityResolver());returncreateSqlSource(configuration,parser。evalNode(script),parameterType);}else{issue127scriptPropertyParser。parse(script,configuration。getVariables());TextSqlNodetextSqlNodenewTextSqlNode(script);判断是否为动态的sql就取决于使用的是{}还是{}当使用{}时就是动态sqlif(textSqlNode。isDynamic()){returnnewDynamicSqlSource(configuration,textSqlNode);}else{returnnewRawSqlSource(configuration,script,parameterType);}}} 之后在RewSqlSource中对sql进行解析 RewSqlSource。java javapublicRawSqlSource(Configurationconfiguration,Stringsql,Classlt;?parameterType){SqlSourceBuildersqlSourceParsernewSqlSourceBuilder(configuration);Classlt;?clazzparameterTypenull?Object。class:parameterType;sqlSourcesqlSourceParser。parse(sql,clazz,newHashMapString,Object());} 解析完最终结果如下 回到上个方法 javavoidparseStatement(Methodmethod){Classlt;?parameterTypeClassgetParameterType(method);LanguageDriverlanguageDrivergetLanguageDriver(method);SqlSourcesqlSourcegetSqlSourceFromAnnotations(method,parameterTypeClass,languageDriver);从这里继续if(sqlSource!null){Optionsoptionsmethod。getAnnotation(Options。class);mappedStatementId类全限定方法名finalStringmappedStatementIdtype。getName()。method。getName();设置获取数据的大小IntegerfetchSizenull;设置此次查询超时时间Integertimeoutnull;https:blog。csdn。netking101125sarticledetails104167493StatementTypestatementTypeStatementType。PREPARED;resultSet结果类型FORWARDONLY光标只能向前移动ResultSetTyperesultSetTypeResultSetType。FORWARDONLY;设置sql类型,当前案例是SELECTSqlCommandTypesqlCommandTypegetSqlCommandType(method);booleanisSelectsqlCommandTypeSqlCommandType。SELECT;booleanflushCache!isSelect;booleanuseCacheisSelect;KeyGeneratorkeyGenerator;StringkeyPropertyid;StringkeyColumnnull;if(SqlCommandType。INSERT。equals(sqlCommandType)SqlCommandType。UPDATE。equals(sqlCommandType)){firstcheckforSelectKeyannotationthatoverrideseverythingelseSelectKeyselectKeymethod。getAnnotation(SelectKey。class);if(selectKey!null){keyGeneratorhandleSelectKeyAnnotation(selectKey,mappedStatementId,getParameterType(method),languageDriver);keyPropertyselectKey。keyProperty();}elseif(optionsnull){keyGeneratorconfiguration。isUseGeneratedKeys()?newJdbc3KeyGenerator():newNoKeyGenerator();}else{keyGeneratoroptions。useGeneratedKeys()?newJdbc3KeyGenerator():newNoKeyGenerator();keyPropertyoptions。keyProperty();keyColumnoptions。keyColumn();}}else{keyGeneratornewNoKeyGenerator();}if(options!null){flushCacheoptions。flushCache();useCacheoptions。useCache();fetchSizeoptions。fetchSize()1options。fetchSize()Integer。MINVALUE?options。fetchSize():null;issue348timeoutoptions。timeout()1?options。timeout():null;statementTypeoptions。statementType();resultSetTypeoptions。resultSetType();}StringresultMapIdnull;ResultMapresultMapAnnotationmethod。getAnnotation(ResultMap。class);if(resultMapAnnotation!null){String〔〕resultMapsresultMapAnnotation。value();StringBuildersbnewStringBuilder();for(StringresultMap:resultMaps){if(sb。length()0){sb。append(,);}sb。append(resultMap);}resultMapIdsb。toString();}elseif(isSelect){resultMapIdparseResultMap(method);}将参数传给小助手assistant。addMappedStatement(mappedStatementId,sqlSource,statementType,sqlCommandType,fetchSize,timeout,ParameterMapIDnull,parameterTypeClass,resultMapId,getReturnType(method),resultSetType,flushCache,useCache,TODOissue577false,keyGenerator,keyProperty,keyColumn,DatabaseIDnull,languageDriver,ResultSetsnull);}} 添加mappedStatement javapublicMappedStatementaddMappedStatement(Stringid,SqlSourcesqlSource,StatementTypestatementType,SqlCommandTypesqlCommandType,IntegerfetchSize,Integertimeout,StringparameterMap,Classlt;?parameterType,StringresultMap,Classlt;?resultType,ResultSetTyperesultSetType,booleanflushCache,booleanuseCache,booleanresultOrdered,KeyGeneratorkeyGenerator,StringkeyProperty,StringkeyColumn,StringdatabaseId,LanguageDriverlang,StringresultSets){if(unresolvedCacheRef){thrownewIncompleteElementException(Cacherefnotyetresolved);}idapplyCurrentNamespace(id,false);booleanisSelectsqlCommandTypeSqlCommandType。SELECT;MappedStatement。BuilderstatementBuildernewMappedStatement。Builder(configuration,id,sqlSource,sqlCommandType)。resource(resource)。fetchSize(fetchSize)。timeout(timeout)。statementType(statementType)。keyGenerator(keyGenerator)。keyProperty(keyProperty)。keyColumn(keyColumn)。databaseId(databaseId)。lang(lang)。resultOrdered(resultOrdered)。resulSets(resultSets)。resultMaps(getStatementResultMaps(resultMap,resultType,id))。resultSetType(resultSetType)。flushCacheRequired(valueOrDefault(flushCache,!isSelect))。useCache(valueOrDefault(useCache,isSelect))。cache(currentCache);ParameterMapstatementParameterMapgetStatementParameterMap(parameterMap,parameterType,id);if(statementParameterMap!null){statementBuilder。parameterMap(statementParameterMap);}MappedStatementstatementstatementBuilder。build();这里将这个MappedStatement放入configurationconfiguration。addMappedStatement(statement);returnstatement;} 将各种参数最后封装为一个MappedStatement,放入configuration中,这样一个addMapper的方法就结束了 之后回到SqlSessionFactory的build中,执行重载的build javapublicSqlSessionFactorybuild(InputStreaminputStream,Stringenvironment,Propertiesproperties){XMLConfigBuilderparsernewXMLConfigBuilder(inputStream,environment,properties);回到这里returnbuild(parser。parse());}默认为DefaultSqlSessionFactorypublicSqlSessionFactorybuild(Configurationconfig){returnnewDefaultSqlSessionFactory(config);} DefaultSqlSessionFactory。java javapublicclassDefaultSqlSessionFactoryimplementsSqlSessionFactory{privatefinalConfigurationconfiguration;publicDefaultSqlSessionFactory(Configurationconfiguration){this。configurationconfiguration;}。。。。。} 至此newSqlSessionFactoryBuilder()。build(inputStream)这段代码的解析环境和加载mapper就分析完了sqlSessionFactory 回到主代码 javapublicstaticvoidmain(String〔〕args)throwsException{Stringresourceorgmybatisconfig。xml;InputStreaminputStreamResources。getResourceAsStream(resource);SqlSessionFactorysqlSessionFactorynewSqlSessionFactoryBuilder()。build(inputStream);SqlSessionsessionsqlSessionFactory。openSession();。。} 开始分析sqlSessionFactory。openSession(); 点进入发现有两个实现类,在上面的build中已经明确了创建的就是DefaultSqlSessionFactory DefaultSqlSessionFactory。java javaOverridepublicSqlSessionopenSession(){参数:执行器,默认为simple,每次关闭statementSimpleExecutorreturnopenSessionFromDataSource(configuration。getDefaultExecutorType(),null,false);} configuration。getDefaultExecutorType()在Configuration类中获取的是本身的一个属性,类型是一个ExecutorType的枚举,默认为SIMPE javaprivateSqlSessionopenSessionFromDataSource(ExecutorTypeexecType,TransactionIsolationLevellevel,booleanautoCommit){Transactiontxnull;try{获取配置类中的事务,datasource封装类finalEnvironmentenvironmentconfiguration。getEnvironment();通过配置的环境中获取事务工厂finalTransactionFactorytransactionFactorygetTransactionFactoryFromEnvironment(environment);创建对象datasource隔离等级是否自动提交txtransactionFactory。newTransaction(environment。getDataSource(),level,autoCommit);finalExecutorexecutorconfiguration。newExecutor(tx,execType);returnnewDefaultSqlSession(configuration,executor,autoCommit);}catch(Exceptione){closeTransaction(tx);mayhavefetchedaconnectionsoletscallclose()throwExceptionFactory。wrapException(Erroropeningsession。Cause:e,e);}finally{ErrorContext。instance()。reset();}} 获取configuration中的事务工厂之后创建一个执行器 Configuration。java javapublicExecutornewExecutor(Transactiontransaction,ExecutorTypeexecutorType){executorTypeexecutorTypenull?defaultExecutorType:executorType;executorTypeexecutorTypenull?ExecutorType。SIMPLE:executorType;Executorexecutor;if(ExecutorType。BATCHexecutorType){executornewBatchExecutor(this,transaction);}elseif(ExecutorType。REUSEexecutorType){executornewReuseExecutor(this,transaction);}else{executornewSimpleExecutor(this,transaction);}if(cacheEnabled){executornewCachingExecutor(executor);}executor(Executor)interceptorChain。pluginAll(executor);returnexecutor;} 这里缓存是默认开启的,所以最后返回的是一个CachingExecutor包含着一个SimpleExecutor 最后返回一个默认的DefaultSqlSession DefaultSqlSession。java javapublicDefaultSqlSession(Configurationconfiguration,Executorexecutor,booleanautoCommit){this。configurationconfiguration;this。executorexecutor;this。dirtyfalse;this。autoCommitautoCommit;} 到这里session也创建完成了之后就是获取mapper执行查询了session。getMapper DefaultSqlSession。java javaOverridepublicTTgetMapper(ClassTtype){returnconfiguration。TgetMapper(type,this);} Configuration。java javapublicTTgetMapper(ClassTtype,SqlSessionsqlSession){returnmapperRegistry。getMapper(type,sqlSession);} MapperRegistry。java javapublicTTgetMapper(ClassTtype,SqlSessionsqlSession){finalMapperProxyFactoryTmapperProxyFactory(MapperProxyFactoryT)knownMappers。get(type);if(mapperProxyFactorynull){thrownewBindingException(TypetypeisnotknowntotheMapperRegistry。);}try{returnmapperProxyFactory。newInstance(sqlSession);}catch(Exceptione){thrownewBindingException(Errorgettingmapperinstance。Cause:e,e);}} MapperProxyFactory。java javaprotectedTnewInstance(MapperProxyTmapperProxy){return(T)Proxy。newProxyInstance(mapperInterface。getClassLoader(),newClass〔〕{mapperInterface},mapperProxy);}publicTnewInstance(SqlSessionsqlSession){finalMapperProxyTmapperProxynewMapperProxyT(sqlSession,mapperInterface,methodCache);returnnewInstance(mapperProxy);} MapperProxy。java 动态代理来实现mapper的方法调用 javapublicclassMapperProxyTimplementsInvocationHandler,Serializable{privatestaticfinallongserialVersionUID6424540398559729838L;privatefinalSqlSessionsqlSession;privatefinalClassTmapperInterface;privatefinalMapMethod,MapperMethodmethodCache;publicMapperProxy(SqlSessionsqlSession,ClassTmapperInterface,MapMethod,MapperMethodmethodCache){this。sqlSessionsqlSession;this。mapperInterfacemapperInterface;this。methodCachemethodCache;}OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object〔〕args)throwsThrowable{if(Object。class。equals(method。getDeclaringClass())){try{returnmethod。invoke(this,args);}catch(Throwablet){throwExceptionUtil。unwrapThrowable(t);}}finalMapperMethodmapperMethodcachedMapperMethod(method);returnmapperMethod。execute(sqlSession,args);}privateMapperMethodcachedMapperMethod(Methodmethod){MapperMethodmapperMethodmethodCache。get(method);if(mapperMethodnull){mapperMethodnewMapperMethod(mapperInterface,method,sqlSession。getConfiguration());methodCache。put(method,mapperMethod);}returnmapperMethod;}} 当我们执行userMapper。getUsers()的时候,通过动态代理进入invoke方法,之后获取缓存的方法,进入cachedMapperMethod 先找是否已经创建过这个方法的封装类了,如果没有则去创建 MapperMethod。java javapublicMapperMethod(Classlt;?mapperInterface,Methodmethod,Configurationconfig){this。commandnewSqlCommand(config,mapperInterface,method);this。methodnewMethodSignature(config,method);} MapperMethod。javaSqlCommand。java静态内部类 javapublicSqlCommand(Configurationconfiguration,Classlt;?mapperInterface,Methodmethod){StringstatementNamemapperInterface。getName()。method。getName();MappedStatementmsnull;当程序走到这里的时候就会为trueif(configuration。hasStatement(statementName)){msconfiguration。getMappedStatement(statementName);}。。。。。。if(msnull){。。。。。}else{namems。getId();typems。getSqlCommandType();if(typeSqlCommandType。UNKNOWN){thrownewBindingException(Unknownexecutionmethodfor:name);}}} Configuration。java javapublicbooleanhasStatement(StringstatementName){returnhasStatement(statementName,true);}publicbooleanhasStatement(StringstatementName,booleanvalidateIncompleteStatements){if(validateIncompleteStatements){buildAllStatements();}主要这行returnmappedStatements。containsKey(statementName);} 可能忘了它什么时候添加进去的了,在那个小助手中的addMappedStatement方法,最后的时候进行的添加点我跳转到addMappedStatement 那么这里就直接走到最后的if了,将name和type赋值给SqlCommand,方法结束 之后还有创建MethodSignature MapperMethod。javaMethodSignature。java静态内部类 javapublicMethodSignature(Configurationconfiguration,Methodmethod){this。returnTypemethod。getReturnType();this。returnsVoidvoid。class。equals(this。returnType);this。returnsMany(configuration。getObjectFactory()。isCollection(this。returnType)this。returnType。isArray());this。mapKeygetMapKey(method);this。returnsMap(this。mapKey!null);是否存在Param注解this。hasNamedParametershasNamedParams(method);this。rowBoundsIndexgetUniqueParamIndex(method,RowBounds。class);this。resultHandlerIndexgetUniqueParamIndex(method,ResultHandler。class);this。paramsCollections。unmodifiableSortedMap(getParams(method,this。hasNamedParameters));} 走完这一系列后回到MapperProxy。java中的invoke方法,最后执行mapperMethod。execute(sqlSession,args) MapperMethod。java javapublicObjectexecute(SqlSessionsqlSession,Object〔〕args){Objectresult;if(){。。。。。。。}elseif(SqlCommandType。SELECTcommand。getType()){if(method。returnsVoid()method。hasResultHandler()){executeWithResultHandler(sqlSession,args);resultnull;}elseif(method。returnsMany()){resultexecuteForMany(sqlSession,args);}elseif(method。returnsMap()){resultexecuteForMap(sqlSession,args);}else{Objectparammethod。convertArgsToSqlCommandParam(args);resultsqlSession。selectOne(command。getName(),param);}}elseif(SqlCommandType。FLUSHcommand。getType()){resultsqlSession。flushStatements();}else{thrownewBindingException(Unknownexecutionmethodfor:command。getName());}if(resultnullmethod。getReturnType()。isPrimitive()!method。returnsVoid()){thrownewBindingException(Mappermethodcommand。getName()attemptedtoreturnnullfromamethodwithaprimitivereturntype(method。getReturnType())。);}returnresult;} 根据command的类型,当前这个案例是SELECT,进入后判断返回类型,当前是返回一个集合,returnsMany属性为ture,进入到resultexecuteForMany(sqlSession,args); javaprivateEObjectexecuteForMany(SqlSessionsqlSession,Object〔〕args){ListEresult;封装入参Objectparammethod。convertArgsToSqlCommandParam(args);这个为false,没有设置过逻辑分页if(method。hasRowBounds()){RowBoundsrowBoundsmethod。extractRowBounds(args);resultsqlSession。EselectList(command。getName(),param,rowBounds);}else{resultsqlSession。EselectList(command。getName(),param);}issue510Collectionsarrayssupportif(!method。getReturnType()。isAssignableFrom(result。getClass())){if(method。getReturnType()。isArray()){returnconvertToArray(result);}else{returnconvertToDeclaredCollection(sqlSession。getConfiguration(),result);}}returnresult;} javapublicObjectconvertArgsToSqlCommandParam(Object〔〕args){finalintparamCountparams。size();if(argsnullparamCount0){returnnull;}elseif(!hasNamedParametersparamCount1){returnargs〔params。keySet()。iterator()。next()〕;}else{finalMapString,ObjectparamnewParamMapObject();inti0;for(Map。EntryInteger,Stringentry:params。entrySet()){param。put(entry。getValue(),args〔entry。getKey()。intValue()〕);issue71,addparamnamesasparam1,param2。。。butensurebackwardcompatibilityfinalStringgenericParamNameparamString。valueOf(i1);if(!param。containsKey(genericParamName)){param。put(genericParamName,args〔entry。getKey()〕);}i;}returnparam;}} 封装mapper入参,没有入参返回null,一个入参返回数组,多个入参返回ParamMap 最终执行到resultsqlSession。selectList(command。getName(),param); DefaultSqlSession。java javapublicEListEselectList(Stringstatement,Objectparameter){returnthis。selectList(statement,parameter,RowBounds。DEFAULT);}OverridepublicEListEselectList(Stringstatement,Objectparameter,RowBoundsrowBounds){try{MappedStatementmsconfiguration。getMappedStatement(statement);returnexecutor。query(ms,wrapCollection(parameter),rowBounds,Executor。NORESULTHANDLER);}catch(Exceptione){throwExceptionFactory。wrapException(Errorqueryingdatabase。Cause:e,e);}finally{ErrorContext。instance()。reset();}} warpCollection方法对入参同一封装了一遍 DefaultSqlSession。java javaprivateObjectwrapCollection(finalObjectobject){如果是集合if(objectinstanceofCollection){StrictMapObjectmapnewStrictMapObject();map。put(collection,object);if(objectinstanceofList){map。put(list,object);}returnmap;如果是数组}elseif(object!nullobject。getClass()。isArray()){StrictMapObjectmapnewStrictMapObject();map。put(array,object);returnmap;}returnobject;} 之后进入executor。query() javaOverridepublicEListEquery(MappedStatementms,Objectparameter,RowBoundsrowBounds,ResultHandlerresultHandler)throwsSQLException{BoundSqlboundSqlms。getBoundSql(parameter);CacheKeykeycreateCacheKey(ms,parameter,rowBounds,boundSql);returnquery(ms,parameter,rowBounds,resultHandler,key,boundSql);} 第一步先获取该方法对应的sql,入参类型,入参参数 ms。getBoundSql(parameter); 之后是创建缓存key javaOverridepublicCacheKeycreateCacheKey(MappedStatementms,ObjectparameterObject,RowBoundsrowBounds,BoundSqlboundSql){if(closed){thrownewExecutorException(Executorwasclosed。);}CacheKeycacheKeynewCacheKey();cacheKey。update(ms。getId());cacheKey。update(Integer。valueOf(rowBounds。getOffset()));cacheKey。update(Integer。valueOf(rowBounds。getLimit()));cacheKey。update(boundSql。getSql());ListParameterMappingparameterMappingsboundSql。getParameterMappings();TypeHandlerRegistrytypeHandlerRegistryms。getConfiguration()。getTypeHandlerRegistry();mimicDefaultParameterHandlerlogicfor(inti0;iparameterMappings。size();i){ParameterMappingparameterMappingparameterMappings。get(i);if(parameterMapping。getMode()!ParameterMode。OUT){Objectvalue;StringpropertyNameparameterMapping。getProperty();if(boundSql。hasAdditionalParameter(propertyName)){valueboundSql。getAdditionalParameter(propertyName);}elseif(parameterObjectnull){valuenull;}elseif(typeHandlerRegistry。hasTypeHandler(parameterObject。getClass())){valueparameterObject;}else{MetaObjectmetaObjectconfiguration。newMetaObject(parameterObject);valuemetaObject。getValue(propertyName);}cacheKey。update(value);}}if(configuration。getEnvironment()!null){issue176cacheKey。update(configuration。getEnvironment()。getId());}returncacheKey;} 创建CacheKey作为缓存key的封装类,根据以下参数进行生成keyMappedStatement的idrowBounds。getOffset()跳过条数rowBounds。getLimit()限制条数boundSql。getSql()要执行的sql语句 之后遍历 如果是数组就将每个元素取出然后执行doUpdate,否则直接执行 CacheKey。java javaprivatevoiddoUpdate(Objectobject){intbaseHashCodeobjectnull?1:object。hashCode();count;checksumbaseHashCode;baseHashCodecount;hashcodemultiplierhashcodebaseHashCode;updateList。add(object);} 最后走到query CachingExecutor。java javaOverridepublicEListEquery(MappedStatementms,ObjectparameterObject,RowBoundsrowBounds,ResultHandlerresultHandler,CacheKeykey,BoundSqlboundSql)throwsSQLException{Cachecachems。getCache();if(cache!null){flushCacheIfRequired(ms);if(ms。isUseCache()resultHandlernull){ensureNoOutParams(ms,parameterObject,boundSql);SuppressWarnings(unchecked)ListElist(ListE)tcm。getObject(cache,key);if(listnull){listdelegate。Equery(ms,parameterObject,rowBounds,resultHandler,key,boundSql);tcm。putObject(cache,key,list);issue578and116}returnlist;}}returndelegate。Equery(ms,parameterObject,rowBounds,resultHandler,key,boundSql);} 因为是首次进入,没有缓存,直接到BaseExecutor。query方法 BaseExecutor。java javaOverridepublicEListEquery(MappedStatementms,Objectparameter,RowBoundsrowBounds,ResultHandlerresultHandler,CacheKeykey,BoundSqlboundSql)throwsSQLException{ErrorContext。instance()。resource(ms。getResource())。activity(executingaquery)。object(ms。getId());if(closed){thrownewExecutorException(Executorwasclosed。);}if(queryStack0ms。isFlushCacheRequired()){clearLocalCache();}ListElist;try{queryStack;listresultHandlernull?(ListE)localCache。getObject(key):null;if(list!null){handleLocallyCachedOutputParameters(ms,key,parameter,boundSql);}else{listqueryFromDatabase(ms,parameter,rowBounds,resultHandler,key,boundSql);}}finally{queryStack;}if(queryStack0){for(DeferredLoaddeferredLoad:deferredLoads){deferredLoad。load();}issue601deferredLoads。clear();if(configuration。getLocalCacheScope()LocalCacheScope。STATEMENT){issue482clearLocalCache();}}returnlist;} 进入后判断如果queryStack0并且当前MappedStatement声明了需要清除缓存,则去清除缓存 javaOptions(flushCacheOptions。FlushCachePolicy。TRUE) xmlselectidgetUserresultTypeuserflushCachetrue 将queryStack,根据CacheKey获取对应缓存,如果没有则去查询数据库 queryStack的作用 BaseExecutor。java javaprivateEListEqueryFromDatabase(MappedStatementms,Objectparameter,RowBoundsrowBounds,ResultHandlerresultHandler,CacheKeykey,BoundSqlboundSql)throwsSQLException{ListElist;localCache。putObject(key,EXECUTIONPLACEHOLDER);try{listdoQuery(ms,parameter,rowBounds,resultHandler,boundSql);}finally{localCache。removeObject(key);}localCache。putObject(key,list);if(ms。getStatementType()StatementType。CALLABLE){localOutputParameterCache。putObject(key,parameter);}returnlist;} 进入doQuery SimpleExecutor。java javaOverridepublicEListEdoQuery(MappedStatementms,Objectparameter,RowBoundsrowBounds,ResultHandlerresultHandler,BoundSqlboundSql)throwsSQLException{Statementstmtnull;try{Configurationconfigurationms。getConfiguration();StatementHandlerhandlerconfiguration。newStatementHandler(wrapper,ms,parameter,rowBounds,resultHandler,boundSql);stmtprepareStatement(handler,ms。getStatementLog());returnhandler。Equery(stmt,resultHandler);}finally{closeStatement(stmt);}} 创建statement执行类 javapublicStatementHandlernewStatementHandler(Executorexecutor,MappedStatementmappedStatement,ObjectparameterObject,RowBoundsrowBounds,ResultHandlerresultHandler,BoundSqlboundSql){StatementHandlerstatementHandlernewRoutingStatementHandler(executor,mappedStatement,parameterObject,rowBounds,resultHandler,boundSql);statementHandler(StatementHandler)interceptorChain。pluginAll(statementHandler);returnstatementHandler;} javapublicRoutingStatementHandler(Executorexecutor,MappedStatementms,Objectparameter,RowBoundsrowBounds,ResultHandlerresultHandler,BoundSqlboundSql){switch(ms。getStatementType()){caseSTATEMENT:delegatenewSimpleStatementHandler(executor,ms,parameter,rowBounds,resultHandler,boundSql);break;casePREPARED:delegatenewPreparedStatementHandler(executor,ms,parameter,rowBounds,resultHandler,boundSql);break;caseCALLABLE:delegatenewCallableStatementHandler(executor,ms,parameter,rowBounds,resultHandler,boundSql);break;default:thrownewExecutorException(Unknownstatementtype:ms。getStatementType());}} 这里使用的是{}MappedStatement的getStatementType返回为PREPARED最后返回PreparedStatementHandler 之后解析prepareStatement javaprivateStatementprepareStatement(StatementHandlerhandler,LogstatementLog)throwsSQLException{Statementstmt;ConnectionconnectiongetConnection(statementLog);stmthandler。prepare(connection);handler。parameterize(stmt);returnstmt;} 获取连接之后解析statement javaOverridepublicStatementprepare(Connectionconnection)throwsSQLException{Statementstatementnull;statementinstantiateStatement(connection);设置超时setStatementTimeout(statement);设置获取数据大小setFetchSize(statement);returnstatement;。。。。} PreparedStatementHandler。java javaOverrideprotectedStatementinstantiateStatement(Connectionconnection)throwsSQLException{StringsqlboundSql。getSql();if(mappedStatement。getKeyGenerator()instanceofJdbc3KeyGenerator){String〔〕keyColumnNamesmappedStatement。getKeyColumns();if(keyColumnNamesnull){returnconnection。prepareStatement(sql,PreparedStatement。RETURNGENERATEDKEYS);}else{returnconnection。prepareStatement(sql,keyColumnNames);}}elseif(mappedStatement。getResultSetType()!null){将会走到这里返回preparedStatementreturnconnection。prepareStatement(sql,mappedStatement。getResultSetType()。getValue(),ResultSet。CONCURREADONLY);}else{returnconnection。prepareStatement(sql);}} 之后执行handler。parameterize(stmt); DefaultParameterHandler。java javaOverridepublicvoidsetParameters(PreparedStatementps){ErrorContext。instance()。activity(settingparameters)。object(mappedStatement。getParameterMap()。getId());ListParameterMappingparameterMappingsboundSql。getParameterMappings();if(parameterMappings!null){for(inti0;iparameterMappings。size();i){ParameterMappingparameterMappingparameterMappings。get(i);if(parameterMapping。getMode()!ParameterMode。OUT){Objectvalue;StringpropertyNameparameterMapping。getProperty();if(boundSql。hasAdditionalParameter(propertyName)){issue448askfirstforadditionalparamsvalueboundSql。getAdditionalParameter(propertyName);}elseif(parameterObjectnull){valuenull;判断入参类型是否有对应的解析类去找TYPEHANDLERMAP中是否存在对应的类型,当前demo的入参类型是int在TypeHandlerRegistry类的无参构造中已经将常用的基本数据类型和引用数据类型放入到了TYPEHANDLERMAP中}elseif(typeHandlerRegistry。hasTypeHandler(parameterObject。getClass())){valueparameterObject;}else{MetaObjectmetaObjectconfiguration。newMetaObject(parameterObject);valuemetaObject。getValue(propertyName);}这里获取的是IntegerTypeHandlerTypeHandlertypeHandlerparameterMapping。getTypeHandler();JdbcTypejdbcTypeparameterMapping。getJdbcType();if(valuenulljdbcTypenull){jdbcTypeconfiguration。getJdbcTypeForNull();}try{IntegerTypeHandler中的并没有重写setParameter进入BaseTypeHandler的setParametertypeHandler。setParameter(ps,i1,value,jdbcType);}catch(TypeExceptione){thrownewTypeException(Couldnotsetparametersformapping:parameterMapping。Cause:e,e);}catch(SQLExceptione){thrownewTypeException(Couldnotsetparametersformapping:parameterMapping。Cause:e,e);}}}}} BaseTypeHandler。java javaOverridepublicvoidsetParameter(PreparedStatementps,inti,Tparameter,JdbcTypejdbcType)throwsSQLException{if(parameternull){if(jdbcTypenull){thrownewTypeException(JDBCrequiresthattheJdbcTypemustbespecifiedforallnullableparameters。);}try{ps。setNull(i,jdbcType。TYPECODE);}catch(SQLExceptione){thrownewTypeException(ErrorsettingnullforparameteriwithJdbcTypejdbcType。TrysettingadifferentJdbcTypeforthisparameteroradifferentjdbcTypeForNullconfigurationproperty。Cause:e,e);}}else{try{进入这里setNonNullParameter(ps,i,parameter,jdbcType);}catch(Exceptione){thrownewTypeException(ErrorsettingnonnullforparameteriwithJdbcTypejdbcType。TrysettingadifferentJdbcTypeforthisparameteroradifferentconfigurationproperty。Cause:e,e);}}} javapublicclassIntegerTypeHandlerextendsBaseTypeHandlerInteger{OverridepublicvoidsetNonNullParameter(PreparedStatementps,inti,Integerparameter,JdbcTypejdbcType)throwsSQLException{ps。setInt(i,parameter);}} 最后回到SimpleExecutor类中的prepareStatement方法,返回PreparedStatement javaOverridepublicEListEdoQuery(MappedStatementms,Objectparameter,RowBoundsrowBounds,ResultHandlerresultHandler,BoundSqlboundSql)throwsSQLException{Statementstmtnull;try{Configurationconfigurationms。getConfiguration();StatementHandlerhandlerconfiguration。newStatementHandler(wrapper,ms,parameter,rowBounds,resultHandler,boundSql);stmtprepareStatement(handler,ms。getStatementLog());获取返回的stmt,进行查询returnhandler。Equery(stmt,resultHandler);}finally{closeStatement(stmt);}} PreparedStatementHandler。java javaOverridepublicEListEquery(Statementstatement,ResultHandlerresultHandler)throwsSQLException{PreparedStatementps(PreparedStatement)statement;ps。execute();returnresultSetHandler。EhandleResultSets(ps);} DefaultResultSetHandler。java javaOverridepublicListObjecthandleResultSets(Statementstmt)throwsSQLException{ErrorContext。instance()。activity(handlingresults)。object(mappedStatement。getId());finalListObjectmultipleResultsnewArrayListObject();intresultSetCount0;先将结果进行封装ResultSetWrapperrswgetFirstResultSet(stmt);。。。。。} javaprivateResultSetWrappergetFirstResultSet(Statementstmt)throwsSQLException{ResultSetrsstmt。getResultSet();while(rsnull){moveforwardtogetthefirstresultsetincasethedriverdoesntreturntheresultsetasthefirstresult(HSQLDB2。1)if(stmt。getMoreResults()){rsstmt。getResultSet();}else{if(stmt。getUpdateCount()1){nomoreresults。Mustbenoresultsetbreak;}}}returnrs!null?newResultSetWrapper(rs,configuration):null;} ResultSetWrapper。java 将结果对应的查询列名,数据库列类型,类名 javapublicResultSetWrapper(ResultSetrs,Configurationconfiguration)throwsSQLException{super();this。typeHandlerRegistryconfiguration。getTypeHandlerRegistry();this。resultSetrs;finalResultSetMetaDatametaDatars。getMetaData();finalintcolumnCountmetaData。getColumnCount();for(inti1;icolumnCount;i){columnNames。add(configuration。isUseColumnLabel()?metaData。getColumnLabel(i):metaData。getColumnName(i));jdbcTypes。add(JdbcType。forCode(metaData。getColumnType(i)));classNames。add(metaData。getColumnClassName(i));}} 回到DefaultResultSetHandler的handleResultSets方法 javaOverridepublicListObjecthandleResultSets(Statementstmt)throwsSQLException{ErrorContext。instance()。activity(handlingresults)。object(mappedStatement。getId());finalListObjectmultipleResultsnewArrayListObject();intresultSetCount0;ResultSetWrapperrswgetFirstResultSet(stmt);ListResultMapresultMapsmappedStatement。getResultMaps();intresultMapCountresultMaps。size();检查查询结果是否指定对应的类或resultMapvalidateResultMapsCount(rsw,resultMapCount);while(rsw!nullresultMapCountresultSetCount){ResultMapresultMapresultMaps。get(resultSetCount);处理结果,当前demo是封装为UserhandleResultSet(rsw,resultMap,multipleResults,null);rswgetNextResultSet(stmt);cleanUpAfterHandlingResultSet();resultSetCount;}。。。。。。。} javaprivatevoidhandleResultSet(ResultSetWrapperrsw,ResultMapresultMap,ListObjectmultipleResults,ResultMappingparentMapping)throwsSQLException{try{if(parentMapping!null){handleRowValues(rsw,resultMap,null,RowBounds。DEFAULT,parentMapping);}else{是否存在自定义的结果处理器if(resultHandlernull){我们没有设置,则使用默认结果处理DefaultResultHandlerdefaultResultHandlernewDefaultResultHandler(objectFactory);处理一行数据handleRowValues(rsw,resultMap,defaultResultHandler,rowBounds,null);multipleResults。add(defaultResultHandler。getResultList());}else{handleRowValues(rsw,resultMap,resultHandler,rowBounds,null);}}}finally{issue228(closeresultsets)closeResultSet(rsw。getResultSet());}} javaprivatevoidhandleRowValues(ResultSetWrapperrsw,ResultMapresultMap,ResultHandlerlt;?resultHandler,RowBoundsrowBounds,ResultMappingparentMapping)throwsSQLException{如果设置了resultMap,我们没有设置,走elseif(resultMap。hasNestedResultMaps()){ensureNoRowBounds();checkResultHandler();handleRowValuesForNestedResultMap(rsw,resultMap,resultHandler,rowBounds,parentMapping);}else{handleRowValuesForSimpleResultMap(rsw,resultMap,resultHandler,rowBounds,parentMapping);}} javaprivatevoidhandleRowValuesForSimpleResultMap(ResultSetWrapperrsw,ResultMapresultMap,ResultHandlerlt;?resultHandler,RowBoundsrowBounds,ResultMappingparentMapping)throwsSQLException{DefaultResultContextObjectresultContextnewDefaultResultContextObject();根据rowBounds跳过行数skipRows(rsw。getResultSet(),rowBounds);判断是否应该处理更多移动resultSet光标并且返回是否还有更多数据while(shouldProcessMoreRows(resultContext,rowBounds)rsw。getResultSet()。next()){ResultMapdiscriminatedResultMapresolveDiscriminatedResultMap(rsw。getResultSet(),resultMap,null);填充值方法ObjectrowValuegetRowValue(rsw,discriminatedResultMap);storeObject(resultHandler,resultContext,rowValue,parentMapping,rsw。getResultSet());}} 判断当前结果上下文是否已经关闭,并且判断当前结果集合总数是否小于rowBounds规定的限制 javaprivatebooleanshouldProcessMoreRows(ResultContextlt;?context,RowBoundsrowBounds)throwsSQLException{return!context。isStopped()context。getResultCount()rowBounds。getLimit();} javaprivateObjectgetRowValue(ResultSetWrapperrsw,ResultMapresultMap)throwsSQLException{finalResultLoaderMaplazyLoadernewResultLoaderMap();创建实体对象ObjectresultObjectcreateResultObject(rsw,resultMap,lazyLoader,null);if(resultObject!null!typeHandlerRegistry。hasTypeHandler(resultMap。getType())){finalMetaObjectmetaObjectconfiguration。newMetaObject(resultObject);booleanfoundValues!resultMap。getConstructorResultMappings()。isEmpty();if(shouldApplyAutomaticMappings(resultMap,false)){foundValuesapplyAutomaticMappings(rsw,resultMap,metaObject,null)foundValues;}foundValuesapplyPropertyMappings(rsw,resultMap,metaObject,lazyLoader,null)foundValues;foundValueslazyLoader。size()0foundValues;resultObjectfoundValues?resultObject:null;returnresultObject;}returnresultObject;} javaprivateObjectcreateResultObject(ResultSetWrapperrsw,ResultMapresultMap,ResultLoaderMaplazyLoader,StringcolumnPrefix)throwsSQLException{finalListClasslt;?constructorArgTypesnewArrayListClasslt;?();finalListObjectconstructorArgsnewArrayListObject();创建对象finalObjectresultObjectcreateResultObject(rsw,resultMap,constructorArgTypes,constructorArgs,columnPrefix);。。。。。returnresultObject;} javaprivateObjectcreateResultObject(ResultSetWrapperrsw,ResultMapresultMap,ListClasslt;?constructorArgTypes,ListObjectconstructorArgs,StringcolumnPrefix)throwsSQLException{finalClasslt;?resultTyperesultMap。getType();获取类的元数据例如类存在几个属性,几个getter几个setter等等类的基本信息finalMetaClassmetaTypeMetaClass。forClass(resultType,reflectorFactory);判断用户是否指明了使用ConstructorArgs来填充参数,当前demo没有,所以这个集合为空finalListResultMappingconstructorMappingsresultMap。getConstructorResultMappings();判断该类是否存在对应的类型处理器if(typeHandlerRegistry。hasTypeHandler(resultType)){returncreatePrimitiveResultObject(rsw,resultMap,columnPrefix);判断是否需要通过有参构造方式填充}elseif(!constructorMappings。isEmpty()){returncreateParameterizedResultObject(rsw,resultType,constructorMappings,constructorArgTypes,constructorArgs,columnPrefix);判断如果当前类hi接口,或者存在默认构造}elseif(resultType。isInterface()metaType。hasDefaultConstructor()){里面最终使用class。newInstance()返回对象returnobjectFactory。create(resultType);}elseif(shouldApplyAutomaticMappings(resultMap,false)){returncreateByConstructorSignature(rsw,resultType,constructorArgTypes,constructorArgs,columnPrefix);}thrownewExecutorException(DonotknowhowtocreateaninstanceofresultType);} 走完这些就会回到DefaultResultSetHandler中的getRowValue方法,其中还有些方法没有对类进行实际修改就省略了 javaprivateObjectgetRowValue(ResultSetWrapperrsw,ResultMapresultMap)throwsSQLException{finalResultLoaderMaplazyLoadernewResultLoaderMap();回到这里ObjectresultObjectcreateResultObject(rsw,resultMap,lazyLoader,null);是否有对应的类型处理器if(resultObject!null!typeHandlerRegistry。hasTypeHandler(resultMap。getType())){finalMetaObjectmetaObjectconfiguration。newMetaObject(resultObject);获取是否通过构造填充参数,当前demo为空取反falsebooleanfoundValues!resultMap。getConstructorResultMappings()。isEmpty();判断是否使用了自动映射https:mybatis。orgmybatis3zhconfiguration。htmlsettingssetting设置autoMappingBehaviorif(shouldApplyAutomaticMappings(resultMap,false)){应用自动映射foundValuesapplyAutomaticMappings(rsw,resultMap,metaObject,null)foundValues;}应用已经映射好的foundValuesapplyPropertyMappings(rsw,resultMap,metaObject,lazyLoader,null)foundValues;判断懒加载或当前填充完成foundValueslazyLoader。size()0foundValues;resultObjectfoundValues?resultObject:null;returnresultObject;}returnresultObject;} javaprivatebooleanapplyAutomaticMappings(ResultSetWrapperrsw,ResultMapresultMap,MetaObjectmetaObject,StringcolumnPrefix)throwsSQLException{创建自动映射的列ListUnMappedColumAutoMappingautoMappingcreateAutomaticMappings(rsw,resultMap,metaObject,columnPrefix);booleanfoundValuesfalse;if(autoMapping。size()0){for(UnMappedColumAutoMappingmapping:autoMapping){finalObjectvaluemapping。typeHandler。getResult(rsw。getResultSet(),mapping。column);issue377,callsetteronnulls如果获取的值不为空,或者允许设置空值if(value!nullconfiguration。isCallSettersOnNulls()){如果value不为空或者值不是基本数据类型if(value!null!mapping。primitive){反射设置值metaObject。setValue(mapping。property,value);}foundValuestrue;}}}returnfoundValues;} javaprivateListUnMappedColumAutoMappingcreateAutomaticMappings(ResultSetWrapperrsw,ResultMapresultMap,MetaObjectmetaObject,StringcolumnPrefix)throwsSQLException{finalStringmapKeyresultMap。getId():columnPrefix;ListUnMappedColumAutoMappingautoMappingautoMappingsCache。get(mapKey);if(autoMappingnull){autoMappingnewArrayListUnMappedColumAutoMapping();获取没有映射的字段名称finalListStringunmappedColumnNamesrsw。getUnmappedColumnNames(resultMap,columnPrefix);for(StringcolumnName:unmappedColumnNames){StringpropertyNamecolumnName;。。。根据名称获取对应实体类的属性名isMapUnderscoreToCamelCase是否开启下划线转到驼峰finalStringpropertymetaObject。findProperty(propertyName,configuration。isMapUnderscoreToCamelCase());if(property!nullmetaObject。hasSetter(property)){获取对应属性的set方法的类型finalClasslt;?propertyTypemetaObject。getSetterType(property);寻找是否有对应的类型转换if(typeHandlerRegistry。hasTypeHandler(propertyType)){finalTypeHandlerlt;?typeHandlerrsw。getTypeHandler(propertyType,columnName);autoMapping。add(newUnMappedColumAutoMapping(columnName,property,typeHandler,propertyType。isPrimitive()));}}}放入缓存autoMappingsCache。put(mapKey,autoMapping);}returnautoMapping;} 之后就是获取ResultSet中的值填充到实体类中 BaseTypeHandler。java javaOverridepublicTgetResult(ResultSetrs,StringcolumnName)throwsSQLException{Tresult;try{resultgetNullableResult(rs,columnName);}catch(Exceptione){thrownewResultMapException(ErrorattemptingtogetcolumncolumnNamefromresultset。Cause:e,e);}if(rs。wasNull()){returnnull;}else{returnresult;}} IntegerTypeHandler。java javaOverridepublicIntegergetNullableResult(ResultSetrs,StringcolumnName)throwsSQLException{returnrs。getInt(columnName);} 这个时候对象已经填充完一个了 之后调用storeObject DefaultResultSetHandler。java javaprivatevoidstoreObject(ResultHandlerlt;?resultHandler,DefaultResultContextObjectresultContext,ObjectrowValue,ResultMappingparentMapping,ResultSetrs)throwsSQLException{if(parentMapping!null){linkToParents(rs,parentMapping,rowValue);}else{进入这里callResultHandler(resultHandler,resultContext,rowValue);}} javaprivatevoidcallResultHandler(ResultHandlerlt;?resultHandler,DefaultResultContextObjectresultContext,ObjectrowValue){将对象存储到resultContextresultContext。nextResultObject(rowValue);((ResultHandlerObject)resultHandler)。handleResult(resultContext);} DefaultResultContext。java javapublicvoidnextResultObject(TresultObject){resultCount;this。resultObjectresultObject;} 之后执行handleResult javapublicclassDefaultResultHandlerimplementsResultHandlerObject{privatefinalListObjectlist;。。。。OverridepublicvoidhandleResult(ResultContextlt;?extendsObjectcontext){list。add(context。getResultObject());}publicListObjectgetResultList(){returnlist;}} 至此一个对象的创建填充就完成了,之后回到DefaultResultSetHandler的handleRowValuesForSimpleResultMap方法继续下一个对象的循环 javaprivatevoidhandleRowValuesForSimpleResultMap(ResultSetWrapperrsw,ResultMapresultMap,ResultHandlerlt;?resultHandler,RowBoundsrowBounds,ResultMappingparentMapping)throwsSQLException{DefaultResultContextObjectresultContextnewDefaultResultContextObject();skipRows(rsw。getResultSet(),rowBounds);一直把result的数据循环完while(shouldProcessMoreRows(resultContext,rowBounds)rsw。getResultSet()。next()){ResultMapdiscriminatedResultMapresolveDiscriminatedResultMap(rsw。getResultSet(),resultMap,null);ObjectrowValuegetRowValue(rsw,discriminatedResultMap);storeObject(resultHandler,resultContext,rowValue,parentMapping,rsw。getResultSet());}} 然后方法一直返回到DefaultResultSetHandler的handleResultSets方法 javaOverridepublicListObjecthandleResultSets(Statementstmt)throwsSQLException{ErrorContext。instance()。activity(handlingresults)。object(mappedStatement。getId());finalListObjectmultipleResultsnewArrayListObject();intresultSetCount0;ResultSetWrapperrswgetFirstResultSet(stmt);ListResultMapresultMapsmappedStatement。getResultMaps();intresultMapCountresultMaps。size();validateResultMapsCount(rsw,resultMapCount);while(rsw!nullresultMapCountresultSetCount){ResultMapresultMapresultMaps。get(resultSetCount);回到这里handleResultSet(rsw,resultMap,multipleResults,null);判断是否存在下一个resultSet一般一个statement只会返回一个resultSetrswgetNextResultSet(stmt);cleanUpAfterHandlingResultSet();resultSetCount;}。。。。。。returncollapseSingleResultList(multipleResults);} javaprivateListObjectcollapseSingleResultList(ListObjectmultipleResults){returnmultipleResults。size()1?(ListObject)multipleResults。get(0):multipleResults;} 最后,返回这个list,整个方法结束