In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly introduces "how to understand SQLSession initialization in Mybatis source code analysis". In daily operation, I believe many people have doubts about how to understand SQLSession initialization in Mybatis source code analysis. Xiaobian consulted all kinds of materials and sorted out simple and easy-to-use methods of operation. I hope it will be helpful to answer the doubts of "how to understand SQLSession initialization in Mybatis source code analysis". Next, please follow the editor to study!
This time I intend to write a series of Mybatis source code analysis, which is roughly divided into
Analysis of Mybatis startup process
Analysis of SQL execution process of Mybatis
The expansion points of Mybatis and its Integration with Spring Boot
This article first analyzes the Mybati initialization process, how to read the configuration file to, and creates a SqlSession example. The main contents include
Read and parse mybatis global configuration files
Mapping mapper.java Fil
Parsing mapper.xml files
Parse the configuration of each node in mapper.xml, including namespace, cache, add, delete, modify and check nodes
Mybatis caching mechanism
Build DefaultSqlSessionFactory
What is SQLSession?
SQLSession provides all the methods needed to interact between the user and the database, hiding the underlying details. The default implementation class is DefaultSqlSession
SQLSession creation example
Through an example provided officially by mybatis, take a look at how to create a SQLSession manually
/ / Mybatis configuration file, which usually contains: database connection information, Mapper.class fully qualified name package path, transaction configuration, plug-in configuration, etc. String resource = "org/mybatis/builder/mybatis-config.xml"; / / read the configuration InputStream inputStream = Resources.getResourceAsStream (resource) in the input stream; / / instantiate the necessary steps of SQLSession SqlSessionFactoryBuilder-- > SqlSessionFactory-- > SqlSessionSqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder (); SqlSessionFactory factory = builder.build (inputStream); SqlSession session = factory.openSession () Read mybatis-config.xml configuration file through input stream
Next, we will start our construction SQLSession source code analysis through new SqlSessionFactoryBuilder ().
/ / SqlSessionFactory has four constructors, all of which will eventually be executed to the full parameter constructor public SqlSessionFactory build (Reader reader, String environment, Properties properties) {try {/ / will instantiate a XMLConfigBuilder first. Here is a basic understanding: XMLConfigBuilder is the XMLConfigBuilder parser = new XMLConfigBuilder (reader, environment, properties) used to parse the configuration of the XML file. / / after parser.parse (), the XML configuration file has been parsed to Configuration, and the Configuration object contains all the properties of mybatis. Return build (parser.parse ());} catch (Exception e) {throw ExceptionFactory.wrapException ("Error building SqlSession.", e);} finally {/ /. Close the stream, throw an exception}}, and take a look at the XMLConfigBuilder class diagram first.
MLConfigBuilder: parsing the global configuration file, namely mybatis-config.xml
XMLMapperBuilder: parses the Mapper file and configures the package path of mapper.java in the mybatis-config.xml file
XMLStatementBuilder: in the node that parses the mapper file, the SQL statement label: select,update,insert,delete
SQLSourceBuilder: dynamically parses SQL statements, parsing tags in Sql statements, such as, etc., according to SqlNode
Of course, there are not only these four implementation classes of BaseBuilder, but only these four categories are introduced here. In the following step-by-step analysis, you can see these figures and take a look at parser.parse ().
Public Configuration parse () {/ / if it has been parsed, throw an exception if (parsed) {throw new BuilderException ("Each XMLConfigBuilder can only be used once.");} / / set the parsing flag bit parsed = true; / / parse the node of mybatis-config.xml, read the configuration file, and load parseConfiguration ("/ configuration") into Configuration; return configuration;} parses xml files into XNode objects through XPathParser objects
Parse the xml configuration file into a XNode object before parsing to Configuration
Public XNode evalNode (Object root, String expression) {/ / mybatis defines a XPathParser object to parse xml. In fact, Document encapsulates Node node = (Node) evaluate (expression, root, XPathConstants.NODE); if (node = = null) {return null;} return new XNode (this, node, variables);} parses each node in config.xml
Let's take a look at how mybatis reads the configuration file step by step.
/ * * resolve configuration nodes of mybatis-config.xml * resolve nodes in XML * / private void parseConfiguration (XNode root) {try {/ * * resolve properties nodes * * resolve to org.apache.ibatis.parsing.XPathParser#variables * org.apache.ibatis.session.Configuration#variables * / propertiesElement (root.evalNode ("properties")) / * parse the settings node in our mybatis-config.xml * which attributes can be configured: http://www.mybatis.org/mybatis-3/zh/configuration.html#settings *. * * / Properties settings = settingsAsProperties (root.evalNode ("settings")); / * * this attribute is hardly used * VFS means virtual file system; it is easy to read file resources in local file system, FTP file system and other systems through programs. VFS is provided in Mybatis. Through this configuration, custom virtual file system applications can be loaded and parsed to: org.apache.ibatis.session.Configuration#vfsImpl * / loadCustomVfs (settings); / * specify the specific implementation of the logs used by MyBatis, which will be found automatically if not specified. * SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING * resolve to org.apache.ibatis.session.Configuration#logImpl * / loadCustomLogImpl (settings); / * * resolve our alias * to oorg.apache.ibatis.session.Configuration#typeAliasRegistry.typeAliases * / typeAliasesElement (root.evalNode ("typeAliases")) / * parse our plug-ins (such as paging plug-ins) * Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed) ParameterHandler (getParameterObject, setParameters) ResultSetHandler (handleResultSets, handleOutputParameters) StatementHandler (prepare, parameterize, batch, update, query) parse to: org.apache.ibatis.session.Configuration#interceptorChain.interceptors * / pluginElement (root.evalNode ("plugins")) ObjectFactoryElement (root.evalNode ("objectFactory")); objectWrapperFactoryElement (root.evalNode ("objectWrapperFactory")); reflectorFactoryElement (root.evalNode ("reflectorFactory")); / / set settings and default settingsElement (settings) / / read it after objectFactory and objectWrapperFactory issue # 631 / * analyze our mybatis environment Parse DataSource * parse to: org.apache.ibatis.session.Configuration#environment * in set In the case of spring, spring-mybatis provides the data source and transaction factory * / environmentsElement (root.evalNode ("environments")) / * * parse database vendor * * resolve to: org.apache.ibatis.session.Configuration#databaseId * / databaseIdProviderElement (root.evalNode ("databaseIdProvider")) / * parse our type processor node * to: org.apache.ibatis.session.Configuration#typeHandlerRegistry.typeHandlerMap * / typeHandlerElement (root.evalNode ("typeHandlers")) / * the most important thing is to parse our mapper * resource: to register the url under our class classpath: to specify the class of our disk or network resources: if you register the Mapper without the xml file, you can directly register the Mapper with the xml file. Need to put xml file and mapper file with the same name in the same path-- >-- > * parse mapper: * 1. Parse the mapper.java interface to: org.apache.ibatis.session.Configuration#mapperRegistry.knownMappers * 2. Parse the mapper.xml configuration * / mapperElement (root.evalNode ("mappers"));} catch (Exception e) {throw new BuilderException ("Error parsing SQL Mapper Configuration. Cause: "+ e, e);}} parsing mapper file parsing mapper.java interface to knowMappers private void mapperElement (XNode parent) throws Exception {if (parent! = null) {/ / get a mapper node for (XNode child: parent.getChildren ()) {/ * specify mapper 4 under our mappers node: * 1. The package path where the specified mapper is located, batch registration * 2. Specify * 3 through the resource directory. Specified by url, from network resources or local disk * 4. Register through the class path * / / determine whether our mapper is through batch registration of if ("package" .equals (child.getName () {String mapperPackage = child.getStringAttribute ("name"); configuration.addMappers (mapperPackage);} else {/ / judge to read our mapper String resource = child.getStringAttribute ("resource") from classpath / / determine whether to read (or obtain from our local disk) String url = child.getStringAttribute ("url") from our network resources; / / parse this type (requires that the interface and xml are in the same package) String mapperClass = child.getStringAttribute ("class") / / parsing the mapper file if (resource! = null & & url = = null & & mapperClass = = null) {ErrorContext.instance () .resource (resource); / / is it deja vu to read a stream from the mapper file? at the beginning, reading the mybatis-config.xml configuration file is also read through the input stream InputStream inputStream = Resources.getResourceAsStream (resource) / / create a read XmlMapper builder object to parse our mapper.xml file. The above-mentioned XMLMapperBuilder object / * read mapper file will be put into the knownMappers in MapperRegistry * Map > knownMappers = new HashMap () * prepare for the subsequent creation of Mapper proxy objects * / XMLMapperBuilder mapperParser = new XMLMapperBuilder (inputStream, configuration, resource, configuration.getSqlFragments ()); / / actually parse our mapper.xml configuration file, and here we will parse our sql mapperParser.parse () } else if (resource = = null & & url! = null & & mapperClass = = null) {ErrorContext.instance (). Resource (url); InputStream inputStream = Resources.getUrlAsStream (url); XMLMapperBuilder mapperParser = new XMLMapperBuilder (inputStream, configuration, url, configuration.getSqlFragments ()); mapperParser.parse ();} else if (resource = = null & & url = = null & & mapperClass! = null) {Class 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.");} parse the mapper.xml file
Parsing SQL tags in Mapper.xml
/ / the parsed SQL statement node will be placed in the Configuration.MappedStatement.SqlSource, and the SqlSource contains each SQLNode, and a tag corresponds to a SQLNodepublic void parse () {/ / to determine whether the current Mapper has been loaded if (! configuration.isResourceLoaded (resource)) {/ / really parse our mapper configurationElement (parser.evalNode ("/ mapper")); / / save the resources to our Configuration configuration.addLoadedResource (resource); bindMapperForNamespace () } parsePendingResultMaps (); parsePendingCacheRefs (); parsePendingStatements ();}
Parsing each node in mapper.xml
/ / parsing our node private void configurationElement (XNode context) {try {/ * parsing our namespace attribute * * / String namespace = context.getStringAttribute ("namespace"); if (namespace = = null | | namespace.equals (")) {throw new BuilderException (" Mapper's namespace cannot be empty ") } / / Save our current namespace and determine the interface full class name = = namespace builderAssistant.setCurrentNamespace (namespace) / * parsing our cache reference * indicates that my current cache reference is the same as DeptMapper's cache reference * resolve to org.apache.ibatis.session.Configuration#cacheRefMap exception (reference cache does not use cache): org.apache.ibatis.session.Configuration#incompleteCacheRefs * / cacheRefElement (context.evalNode ("cache")) / * parse our cache node * to: org.apache.ibatis.session.Configuration#caches org.apache.ibatis.builder.MapperBuilderAssistant#currentCache * / cacheElement (context.evalNode ("cache")); / * * parse paramterMap node * / parameterMapElement (context.evalNodes ("/ mapper/parameterMap")) / * resolve our resultMap node * parse to: org.apache.ibatis.session.Configuration#resultMaps * exception org.apache.ibatis.session.Configuration#incompleteResultMaps * * / resultMapElements (context.evalNodes ("/ mapper/resultMap")) / * parsing We parse to org.apache.ibatis.builder.xml.XMLMapperBuilder#sqlFragments * through the sql node * is actually equal to org.apache.ibatis.session.Configuration#sqlFragments * because they are the same reference, and the Configuration.getSqlFragments is passed in * / sqlElement (context.evalNodes ("/ mapper/sql") when building XMLMapperBuilder) / * parse our select | insert | update | delete node * parse to org.apache.ibatis.session.Configuration#mappedStatements * eventually the SQL node will be parsed to MappedStatement, and a node corresponds to a MappedStatement * precisely, the sql node is parsed into SQLNode encapsulated in MappedStatement.SqlSource * SQLNode corresponds to the child tags in the sql node, such as Wait for * / 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);}}
Focus on the analysis of several analytical processes
The parsing cache private void cacheElement (XNode context) {if (context! = null) {/ * cache element can specify the following attributes, each of which is specified as a decoration for the underlying Cache Uses the decorator's mode * cache attribute: * 1.eviction: cache expiration policy: default is LRU * LRU-the least recently used: remove objects that have not been used for the longest time. -- > LruCache * FIFO-FIFO: remove objects in the order in which they enter the cache. -- > FifoCache * SOFT-soft reference: remove objects based on garbage collector status and soft reference rules. -- > SoftCache * WEAK-weak references: more actively remove objects based on garbage collector state and weak reference rules. -- > WeakCache * 2.flushInterval: the interval between emptying the cache (in milliseconds). If it is specified, it will be encapsulated with ScheduleCache * 3.size: the size of the cache object, default is 1024, which is for LruCache. LruCache only stores a maximum of 1024 Key * 4.readOnly by default: false by default, and the underlying SerializedCache wrapper, which serializes cache objects when caching is written. Then deserialize when reading the cache, so that each time you read a new object, even if you change the read result, it will not affect the original cached object. True- returns the same instance of cache object to all callers * 5.blocking: default is false. When true is specified, it will be encapsulated with BlockingCache. After adding, deleting and modifying concurrent queries, only one query will go to the database instead of concurrent access. * 6.type: type attribute is used to specify the current underlying cache implementation class. Default is PerpetualCache. If we want to use custom Cache You can specify it through this attribute, and the corresponding value is the full path name of our custom Cache * / / resolve the type attribute of the cache node String type = context.getStringAttribute ("type", "PERPETUAL") / / obtain the class type Class according to the String of type, in MapperProxyFactory > knownMappers
Step 3: read the mapper.xml node
1. The mapper.xml file is also read as an input stream. Parsing each pin attribute in mapper.xml file through XMLMapperBuilder instance
Parsing namespace attributes
Resolve cache reference cache-ref
Parsing cache Node
Parsing resultMap Node
Parsing sql Node
Parse select | insert | update | delete node 3. Parsing SQL tags through XMLStatementBuilder
Step 4: encapsulate all the configuration properties into the Configuration object to build a SqlSessionFactory factory instance step 5: open a data source SqlSessionFactory#openSession () from session, the default is DefaultSqlSession, on the "Mybatis source code analysis of how to understand SQLSession initialization" learning is over, hope to solve everyone's doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.