preface

In the previous several articles, we briefly explained the simple usage of MyBatis, and the use of one-to-one, one-to-many and many-to-many related dynamic SQL query tags. We also mentioned the N+1 problem caused by nested queries, and related functions of lazy loading. This article will start from the underlying implementation of MyBatis. To analyze the four core objects of MyBatis.

Four core objects of MyBatis

Let’s recall the steps to complete a database operation with MyBatis from the previous article, as shown below:

! [](https://upload-images.jianshu.io/upload_images/17138799-f62f0bdfef7a36f4? imageMogr2/auto-orient/strip|imageView2/2/w/917/format/webp)

It can be concluded that the steps are as follows:

  • 1. Load the configuration file
  • 2. Get the SqlSessionFactoryBuiler object
  • Get the SqlSessionFactory object from the SqlSessionFactoryBuiler and configuration file stream
  • 4. Open a SqlSession using the SqlSessionFactory object
  • 5, through SqlSession to obtain the corresponding Mapper object
  • 6, through Mapper object to call the corresponding interface to query the database

From these steps we can see that MyBatic completes a database operation with four core objects: SqlSessionFactoryBuiler, SqlSessionFactory, SqlSession and Mapper.

SqlSessionFactoryBuiler

The only purpose of SqlSessionFactoryBuilder is to create the SqlSessionFactory. It is not used once it is created, so the SqlSessionFactoryBuiler life cycle is extremely short.

SqlSessionFactoryBuiler provides nine methods that return the SqlSessionFactory object.

! [](https://upload-images.jianshu.io/upload_images/17138799-c05927b9241bfee3? imageMogr2/auto-orient/strip|imageView2/2/w/600/format/webp)

The Builder mode is used in SqlSessionFactoryBuiler

(2+1) method analysis

There are nine methods, but we can actually view it as (2+1) methods. As you can see in the figure below, the first three methods all end up calling the fourth method, so they are actually one method

! [](https://upload-images.jianshu.io/upload_images/17138799-495ac2142a77f357? imageMogr2/auto-orient/strip|imageView2/2/w/834/format/webp)

Three methods end up calling the same method:

! [](https://upload-images.jianshu.io/upload_images/17138799-1c59db7be8f1e9b0? imageMogr2/auto-orient/strip|imageView2/2/w/911/format/webp)

So these two methods correspond to the 2 in the 2+1 method.

As you can also see in the figure above, after parsing the Configuration file into a Java Configuration class, the two methods simultaneously call another method, build(Configuration Config), which does nothing. Passing in the configuration class returns a DefaultSqlSessionFactory object, which is the implementation class for SqlSessionFactory

! [](https://upload-images.jianshu.io/upload_images/17138799-e3fc2de6442a8c78? imageMogr2/auto-orient/strip|imageView2/2/w/669/format/webp)

Insert a picture description here

So the 1 of 2+1 is nothing to analyze, so the 2 actually supports two ways to read files. For example, we can get an SqlSessionFactory object by using the following methods:

String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
Copy the code

But we could have gotten the SqlSessionFactory object as well:

Reader reader = Resources.getResourceAsReader(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
Copy the code

The only difference between these two methods is that in this case, the other two parameters are the same.

  • String environment: This is used to determine which environment to load.

    The following figure is our mybatis file, which defines an environment ID. When we need to support multi-loop data source switching, we can define multiple ids, and then pass in different ids according to different environments.

    ! [](https://upload-images.jianshu.io/upload_images/17138799-224c288fc95acd73? imageMogr2/auto-orient/strip|imageView2/2/w/875/format/webp)

    Insert a picture description here

  • Properties Properties: The Properties in our dataSource below are not entered directly, but are configured with ${jdbc.driver}, and the values of these Properties can be maintained in a separate Properties file. [Image upload failed…(image-689Cd-1604121808670)]

    Then the code can be rewritten like this:

Reader reader = Resources.getResourceAsReader(resource);
        Properties properties = Resources.getResourceAsProperties("db.properties");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader,properties);
Copy the code

With this approach, the mybatis-config. XML file can be directly valued with ${}. There is also an easier way to import the properties file in mybatis-config. XML instead of parsing the properties file in code:

<properties resource="db.properties"></properties>
Copy the code

! [](https://upload-images.jianshu.io/upload_images/17138799-b402e73684be892d? imageMogr2/auto-orient/strip|imageView2/2/w/620/format/webp)

Most people don’t use properties files today, but it was pretty common when I first started learning programming.

The build() method reads an XML file and encapsulates the read information into a Congiguration, but we won’t go into how to parse an XML file beyond the focus of this article.

It is also easy to see from the above analysis that there is a way to pass in a Congiguration to the SqlSessionFactory object without using XML. Instead, you build a Congiguration directly from Java code and get the SqlSessionFactory object directly. As follows:

Configuration congiguration = new Configuration();
        congiguration.setDatabaseId("xxx");
        congiguration.setCacheEnabled(false);
        SqlSessionFactory sqlSessionFactory1 = new SqlSessionFactoryBuilder().build(congiguration);
Copy the code

Of course, if you need to change the code every time in this way, it will be more troublesome and less intuitive, so IT is recommended to use XML to configure the basic attributes of MyBatis.

InputStream and Reader

Reader and InputStream are two ways to read files provided by the Java I/O library. Readers are used to read 16-bit characters, which are Unicode encoded characters; InputStream is used to read ASCII characters and binary data. I’ll separate out this distinction and summarize the input and output streams in Java. If you’re interested, follow me and keep an eye on my blog. I’m not going to go over these two ways here, but what you need to know here is that these are two different input ways.

SqlSessionFactory

SqlSessionFactory is an interface, the default implementation class, is used to generate SqlSession objects, and SqlSession objects need to be created continuously, so the SqlSessionFactory exists globally, and there is no need to create SqlSessionFactory repeatedly. So this is a singleton.

SqlSessionFactory, as the name suggests, uses the factory design pattern

SqlSessionFactory has only two implementation classes: DefaultSqlSessionFactory and SqlSessionManager.

DefaultSqlSessionFactory

DefaultSqlSessionFactory is the default implementation class of SqlSessionFactory, which is basically what we use today. This class provides eight methods to get the SqlSession object. This screenshot is not easy to capture, so I listed the methods for comparison:

SqlSession openSession();
SqlSession openSession(boolean autoCommit);
SqlSession openSession(TransactionIsolationLevel level);
SqlSession openSession(ExecutorType execType,TransactionIsolationLevel level);
SqlSession openSession(ExecutorType execType);
SqlSession openSession(ExecutorType execType, boolean autoCommit);
SqlSession openSession(Connection connection);
SqlSession openSession(ExecutorType execType, Connection connection);
Copy the code

TransactionIsolationLevel and the autoCommit mode in the eight methods are better understood, is whether the transaction isolation level and open automatically submit. In front of the six methods actually call openSessionFromDataSource method finally, behind the two is called the openSessionFromConnection method.

! [](https://upload-images.jianshu.io/upload_images/17138799-8d2370ace59f18f0? imageMogr2/auto-orient/strip|imageView2/2/w/1083/format/webp)

! [](https://upload-images.jianshu.io/upload_images/17138799-335b97b2896af11f? imageMogr2/auto-orient/strip|imageView2/2/w/964/format/webp)

Obviously from the two methods above screenshot you can see, these two methods is essentially the same, the only difference is that the openSessionFromConnection method gets the current session from the Connection object whether need open automatically submit.

Executor

The Executor object is used to execute SQL statements in MyBatis. There are only three types of executors: SIMPLE, REUSE, and BATCH. The SimpleExecutor executor corresponding to the SIMPLE type is used by default. SimpleExecutor represents a plain executor that does nothing. REUSE corresponds to the ReuseExecutor executor, which reuses preprocessed statements. BATCH corresponds to the BatchExecutor executor, which is used to perform BATCH operations. Executor is one of the four objects that belong to SqlSession, and there will be a blog post devoted to that, but we won’t go into it here.

SqlSessionManager

SqlSessionManager is not really new, it just brings the SqlSessionFactory and SqlSession responsibilities together, so we won’t discuss this much. [image upload failed…(image-871850-1604121808671)]

SqlSession

SqlSession is used to operate THE XML file in our written SQL statement, each operation database we need a SqlSession object, SqlSession is used to connect with the transaction in the database, so SqlSession is included in the transaction isolation level and other information.

SqlSession instances are thread-safe, so the best range of requests is request or method.

SqlSession is also an interface and has two implementation classes: DefaultSqlSession and SqlSessionManager. SqlSessionManager () : SqlSessionManager () : SqlSessionManager () : SqlSessionManager ()

! [](https://upload-images.jianshu.io/upload_images/17138799-7449207ea32b4fc3? imageMogr2/auto-orient/strip|imageView2/2/w/827/format/webp)

Mapper

Mapper is an interface without any implementation classes. The Mapper instance scope is the same or smaller than SqlSession. The Mapper instance scope is the same or smaller than SqlSession. The scope of Mapper instances is best kept at the scope of methods, otherwise it becomes difficult to manage.

The name of the Mapper interface must be the same as the name of the XML file that corresponds to the SQL statement. The method name defined in the Mapper interface corresponds to the statement ID in the XML file.

Four object life cycles

SqlSessionFactoryBuiler is used only when the SqlSessionFactory object is created and then discarded. SqlSessionFactory is globally unique and is a singleton object, but needs to exist globally. SqlSession generally corresponds to a request, Mapper is generally controlled in the method.

object The life cycle
SqlSessionFactoryBuiler Method parts are discarded when used
SqlSessionFactory The Application level, which exists globally, is a singleton
SqlSession Request or Method (Request/Method)
Mapper Method (Method)

conclusion

This article mainly analyzes the four core object: in the MyBatis SqlSessionFactoryBuiler, SqlSessionFactory, SqlSession, Mapper. The generation process and life cycle of the four objects are analyzed from the perspective of source code. In the next article, we’ll look at the SqlSession execution process and see how our parameters and result sets are mapped.