MYBATIS3 Source Analysis (iii): Parsing the mapper XML configuration file

Source: Internet
Author: User
Tags throw exception

In this chapter we look at how MyBatis reads the Mapper XML configuration file and resolves the SQL statements in it.

We also remember that this is the configuration of sqlsessionfactory:

<bean id= "Sqlsessionfactory" class= "Org.mybatis.spring.SqlSessionFactoryBean" >       <property name= " DataSource "ref=" DataSource "/>     <property name=" configlocation "value=" Classpath:configuration.xml "> </property>      <property name= "mapperlocations" value= "Classpath:com/xxx/mybatis/mapper/*.xml"/>       <property name= "typealiasespackage" value= "Com.tiantian.mybatis.model"/>    </bean>  

Here you configure a Mapperlocations property, which is an expression, Sqlsessionfactory will read all the XML format files below the package com.xxx.mybaits.mapper based on this expression, so how do you read the configuration file based on this property?

The answer is in the Buildsqlsessionfactory method in the Sqlsessionfactorybean class:

if (!isempty (this.mapperlocations)) {for      (Resource mapperLocation:this.mapperLocations) {        if ( Mapperlocation = = null) {          continue;        }        try {          Xmlmapperbuilder xmlmapperbuilder = new Xmlmapperbuilder (Mapperlocation.getinputstream (),              Configuration, Mapperlocation.tostring (), configuration.getsqlfragments ());          Xmlmapperbuilder.parse ();        } catch (Exception e) {          throw new Nestedioexception ("Failed to parse Mapping resource: '" + mapperlocation + "'", e); 
   } finally {          errorcontext.instance (). reset ();        }        if (logger.isdebugenabled ()) {          logger.debug ("Parsed mapper file: '" + mapperlocation + "'");}}}    

MyBatis uses an instance of the Xmlmapperbuilder class to parse the mapper configuration file.

Public Xmlmapperbuilder (Reader reader, configuration configuration, String resource, map<string, xnode> sqlfragments) {This    (new Xpathparser (reader, True, Configuration.getvariables (), New Xmlmapperentityresolver ()),        configuration, resource, sqlfragments);  }

Private Xmlmapperbuilder (Xpathparser parser, configuration configuration, String resource, map<string, xnode> sqlfragments) {    super (configuration);    This.builderassistant = new Mapperbuilderassistant (configuration, Resource);    This.parser = parser;    this.sqlfragments = sqlfragments;    This.resource = resource;  }

The system then calls Xmlmapperbuilder's Parse method to parse the mapper.

public void Parse () {    ///If the configuration object has not yet loaded the XML config file (to avoid repeated loading, it is actually a confirmation that the properties and contents of the Mapper node are resolved,    //To parse its child nodes such as cache, SQL, select, Resultmap, Parametermap, etc.),    //The mapper node is parsed from the input stream, then the status of resource is set to the loaded    if (! Configuration.isresourceloaded (Resource)) {      configurationelement (Parser.evalnode ("/mapper"));      Configuration.addloadedresource (Resource);      Bindmapperfornamespace ();    }    Resolves a <resultMap> node    parsependingresultmaps () whose extends attribute points to a parent object that is not processed while processing resultmap in the ConfigurationElement function ;    Resolves an <cache> node where the object it points to when processing cache-ref in the ConfigurationElement function (if Cache-ref is loaded before the cache node to which it points)    Parsependingchacherefs ();    Ditto, if the cache does not load the processing statement will also throw exception    parsependingstatements ();  }

The process of

     mybatis parsing mapper XML files is already obvious, so let's see how it resolves mapper:

private void ConfigurationElement (XNode context) {try {//Get Mapper Node Namespace Property String Namespace = context.      Getstringattribute ("namespace");      if (Namespace.equals (")) {throw new Builderexception (" Mapper ' s namespace cannot be empty ");      }//Set current namespace Builderassistant.setcurrentnamespace (namespace);      Parse Mapper's <cache-ref> node cacherefelement (Context.evalnode ("Cache-ref"));      Parse Mapper's <cache> node cacheelement (context.evalnode ("cache"));      Parse Mapper's <parameterMap> node parametermapelement (context.evalnodes ("/mapper/parametermap"));      Parse Mapper's <resultMap> node resultmapelements (context.evalnodes ("/mapper/resultmap"));      Parse Mapper's <sql> node sqlelement (context.evalnodes ("/mapper/sql")); Use Xmlstatementbuilder objects to resolve mapper <select>, <insert>, <update>, <delete> nodes,// Mybaits will use the Mappedstatement.builder class to build a Mappedstatement object,//So mybaits one SQL corresponds to a mappeDstatement Buildstatementfromcontext (Context.evalnodes ("Select|insert|update|delete")); } catch (Exception e) {throw new Builderexception ("Error parsing Mapper XML.    Cause: "+ E, E); }  }

The ConfigurationElement function almost parses all the child nodes under the Mapper node, so mybaits resolves all the nodes in the mapper. It is added to the configuration object to be available to the Sqlsessionfactory object at any time. Here we need to add a little bit more about how Mybaits uses the Parsestatementnode function of an object of the Xmlstatementbuilder class to borrow Mapperbuilderassistant class object builderassistant Tatement parses the Mappedstatement and associates it to the configuration class object:

public void Parsestatementnode () {//id property String id = context.getstringattribute ("id");    DatabaseId Property String databaseId = Context.getstringattribute ("DatabaseId");    if (!databaseidmatchescurrent (ID, databaseId, This.requireddatabaseid)) {return;    }//fetchsize Property Integer fetchsize = Context.getintattribute ("Fetchsize");    Timeout Property Integer timeout = Context.getintattribute ("timeout");    Parametermap Property String Parametermap = Context.getstringattribute ("Parametermap");    ParameterType property String parametertype = Context.getstringattribute ("ParameterType");    class<?> Parametertypeclass = Resolveclass (parametertype);    Resultmap Property String Resultmap = Context.getstringattribute ("Resultmap");    Resulttype Property String Resulttype = Context.getstringattribute ("Resulttype");    Lang property String lang = Context.getstringattribute ("lang");    Languagedriver langdriver = getlanguagedriver (lang); class<?> Resulttypeclass = Resolveclass (Resulttype);    ResultsetType Property String ResultsetType = Context.getstringattribute ("ResultsetType"); StatementType StatementType = statementtype.valueof (Context.getstringattribute ("StatementType",    StatementType.PREPARED.toString ()));    ResultsetType resultsettypeenum = Resolveresultsettype (ResultsetType);    String nodeName = Context.getnode (). Getnodename ();    Sqlcommandtype Sqlcommandtype = sqlcommandtype.valueof (Nodename.touppercase (locale.english));    Is the <select> node Boolean isselect = Sqlcommandtype = = Sqlcommandtype.select;    Flushcache attribute Boolean flushcache = Context.getbooleanattribute ("Flushcache",!isselect);    UseCache attribute Boolean usecache = Context.getbooleanattribute ("UseCache", isselect);    Resultordered Property Boolean resultordered = Context.getbooleanattribute ("resultordered", false); Include fragments before parsing xmlincludetransformer includeparser = new Xmlincludetransformer (Configuration, Buil    Derassistant); Includeparser.appLyincludes (Context.getnode ());    Parse Selectkey after includes and remove them.        Processselectkeynodes (ID, Parametertypeclass, langdriver); Parse the SQL (pre: <selectKey> and <include> were parsed and removed) sqlsource Sqlsource = Langdriver.    Createsqlsource (configuration, context, parametertypeclass);    ResultSets property String resultsets = Context.getstringattribute ("resultsets");    Keyproperty Property String Keyproperty = Context.getstringattribute ("Keyproperty");    KeyColumn Property String KeyColumn = Context.getstringattribute ("KeyColumn");    Keygenerator Keygenerator;    String Keystatementid = id + selectkeygenerator.select_key_suffix;    Keystatementid = Builderassistant.applycurrentnamespace (Keystatementid, true);    if (Configuration.haskeygenerator (Keystatementid)) {keygenerator = Configuration.getkeygenerator (keyStatementId);    } else {//usegeneratedkeys property Keygenerator = Context.getbooleanattribute ("Usegeneratedkeys",      Configuration.isusegeneratedkeys () && SqlCommandType.INSERT.equals (sqlcommandtype))?    New Jdbc3keygenerator (): New Nokeygenerator (); } builderassistant.addmappedstatement (ID, Sqlsource, StatementType, Sqlcommandtype, fetchsize, timeout, paramete         RMap, Parametertypeclass, Resultmap, Resulttypeclass, Resultsettypeenum, Flushcache, UseCache, resultOrdered,  Keygenerator, Keyproperty, KeyColumn, DatabaseId, Langdriver, resultsets); }
It can be seen from the above code that Mybaits uses XPath to parse Mapper's configuration file, Resultmap, Parametermap, Cache, Nodes such as statement use the associated builder to create and associate the resulting object to the configuration object, which can be obtained from the sqlsession. This explains how we mybaits get to Mapper and execute the SQL statements in the database as we work with sqlsession.









MYBATIS3 Source Analysis (iii): Parsing the mapper XML configuration file

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.