Mainly explains the execution process of SQL in MyBatis, based on the basic knowledge of MyBatis deeper analysis.

preface

In “[MyBatis Series 1] Basic Knowledge (PART 1)”, we explained the working principle of MyBaits and the use posture of its four core components. Including SqlSessionFactoryBuilder, SqlSessionFactory, SqlSession and SQL Mapper. In [MyBatis Series 1] Basic Knowledge (Part 2), the XML configuration file of MyBatis is explained in detail through a complete example of using MayBatis.

Therefore, before reading this article, it is recommended that you first read the first and the next two articles of “[MyBatis Series 1] Basic Knowledge”. This article is mainly based on SQL execution process, and explains the basic knowledge of MyBatis in a deeper level. The basic knowledge that has been talked about before will be directly skipped.

MyBatis overall architecture

MyBatis is on top of the interface layer, the interface layer is the developer in Mapper or Dao interface definition, is query, add, update or delete operations; The middle layer is the data processing layer, which is mainly the process of configuring parameter mapping, SQL parsing, SQL execution and result mapping between Mapper -> XML levels. Both processes are supported by basic support layers, including connection management, transaction management, configuration loading, cache handling, and so on.

The interface layer

Without integration with Spring, MyBatis performs database operations as follows:

InputStream is = Resources.getResourceAsStream("myBatis-config.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(is);
sqlSession = factory.openSession();
Copy the code

SqlSessionFactory, SqlSession is the core of the MyBatis interface classes, especially the SqlSession, the interface is the most important thing in MyBatis interface, this interface allows you to execute the command, mapping, management affairs.

For the extension of this knowledge, please refer to “[MyBatis Series 1] Basic Knowledge (PART 1)”.

Data processing layer

Configure the parsing

During the initialization of Mybatis, the Mybatis -config. XML configuration file, mapping configuration file, and annotation information in Mapper interface will be loaded. The parsed configuration information will be formed into an object and stored in the Configration object. The SqlSessionFactory object is then created from that object. After Mybatis initialization is complete, you can use SqlSessionFactory to create SqlSession objects and start database operations.

For the extension of this knowledge, please refer to “[MyBatis Series 1] Basic Knowledge (PART 1)”.

SQL parsing and scripting modules

Mybatis dynamic SQL statement, almost all can be written to meet the needs of THE SQL.

The Scripting module in Mybatis parses the dynamic SQL nodes defined in the mapping file according to the parameters passed in by the user and forms SQL statements that can be executed by the database.

SQL execution

SQL statement execution involves multiple components, including the four cores of MyBatis: Executor, StatementHandler, ParameterHandler, ResultSetHandler. The SQL execution process can be represented by the following diagram:

MyBatis hierarchical structure of each component introduction:

  • SqlSession: It is MyBatis core API, mainly used to execute commands, obtain mappings, and manage transactions. Receive the Statement Id and parameters from the developer. And return the operation result.
  • Executor: An Executor that is the core of MyBatis scheduling and is responsible for generating SQL statements and maintaining the query cache.
  • StatementHandler: encapsulates the JDBC Statement operation and performs operations on the JDBC Statement, such as setting parameters and converting the Statement result set to a List.
  • ParameterHandler: converts user-passed parameters to those required for a JDBC Statement.
  • ResultSetHandler: Is responsible for converting a ResultSet object returned by JDBC into a collection of type List.
  • TypeHandler: Used for converting between Java and JDBC types.
  • MappedStatement: Encapsulates dynamic SQL
  • SqlSource: Represents the content of a mapping statement read from an XML file or comment, which creates the SQL that passes input parameters received from the user to the database.
  • Configuration: All the Configuration information of MyBatis is kept in the Configuration object.

Framework support layer

  • Reflection module: Reflection module in Mybatis, has a good encapsulation of Java reflection, provides a simple API, convenient upper-layer call, and a series of optimization of reflection operations, such as caching MetaClass and MetaObject metadata, Improved performance of reflection operation.
  • Type conversion module: Alias mechanism of Mybatis, can simplify configuration files, this mechanism is one of the main functions of type conversion module. Another function of the type conversion module is to convert JDBC types to Java types. When SQL statements bind parameters, the data is converted from Java type to JDBC type. When the result set is mapped, the data is converted from the JDBC type to the Java type.
  • Logging module: In Java, there are many excellent logging frameworks, such as Log4j, Log4j2, SLF4J, etc. In addition to providing detailed log output information, Mybatis can integrate multiple log frameworks. The main function of its log module is to integrate third-party log frameworks.
  • Resource loading module: This module mainly encapsulates the class loader, determines the use sequence of the class loader, and provides the function of loading class files and other resource files.
  • Parser module: This module has two main functions: one is to encapsulate XPath and provide support for parsing Mybatis -config. XML configuration file and mapping configuration file during Mybatis initialization; The other provides support for handling placeholders in dynamic SQL statements.
  • Data source module: Mybatis itself provides the corresponding data source implementation, but also provides the interface to integrate with the third-party data source. Data source is one of the common components in development. Many open source data sources provide rich functions, such as connection pooling, connection status detection, etc. Selecting data source components with excellent performance is very important for providing ORM framework and the performance of the whole application.
  • Transaction Management module: Generally, Mybatis integrates with the Spring framework, which manages transactions. However, Mybatis abstracts the database transaction itself, and provides the corresponding transaction interface and simple implementation.
  • Cache module: Mybatis has level 1 cache and level 2 cache, both of which depend on the implementation in the cache module. However, it should be noted that these two levels of cache, Mybatis and the entire application run in the same JVM and share the same memory. If the amount of data in these two levels is large, other functions in the system may be affected. Therefore, if a large amount of data needs to be cached, the use of cache products such as Redis and Memcache is preferred.
  • Binding module: SQL nodes defined in the mapping file need to be specified when the corresponding SqlSession method is called to perform database operations. If there are spelling errors in the SQL, they can only be detected at run time. In order to detect such errors as soon as possible, Mybatis associates the user-defined Mapper interface with the mapping file through the Binding module, and the system can execute the corresponding SQL statement to complete the database operation by calling the methods in the user-defined Mapper interface, thus avoiding the above problems. Note that in development, we only created the Mapper interface and did not write the implementation class, because Mybatis automatically created dynamic proxy objects for the Mapper interface.

MySQL execution process

This is also an excerpt from the online blog, because the main source code should include, I will remove the source code part, only retain the content of the explanation process.

SqlSessionFactory

SqlSessionFactory has two implementation classes: SqlSessionManager and DefaultSqlSessionFactory:

  • DefaultSqlSessionFactory: The default implementation class for SqlSessionFactory, which is a factory class that actually produces sessions. Instances of this class have a global lifecycle, generating only one instance (singleton mode) on the first invocation and remaining until the server is shut down.
  • SqlSessionManager: deprecated SqlSessionManager needs to maintain its own thread pool. MyBatis is more about integrating with Spring than using it alone, so it doesn’t make sense to maintain your own ThreadLocal. So SqlSessionManager is no longer in use.

SqlSessionFactory = SqlSessionFactory = SqlSessionFactory

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
Copy the code

Starting with this line of code, we first create an SqlSessionFactoryBuilder factory. This is a builder pattern design idea. The Builder creates the SqlSessionFactory factory

Then call the build method in SqlSessionFactoryBuilder and pass in an InputStream. The InputStream is the mybatis-config.xml configuration file that you pass in. SqlSessionFactoryBuilder creates an XMLConfigBuilder object from the incoming InputStream InputStream and the environment and properties properties.

SqlSessionFactoryBuilder -> SqlSessionFactory -> SqlSession For the field meanings in THE XML configuration, see [MyBatis Series 1] Basic Knowledge (Part 2).

SqlSession

The SqlSession is obtained from the SqlSessionFactory object, and the SQL statement can be executed. In SqlSessionFactory openSession process, it will call in to the DefaultSqlSessionFactory openSessionFromDataSource method, This method primarily creates two objects that are important to our analysis of the execution flow, an Executor Executor object and a SqlSession object.

SqlSession object is one of the most important objects in MyBatis. This interface allows you to execute commands, get mappings, and manage transactions. SqlSession allows you to perform simple CRUD operations. You can also use getMapper to access the Mapper layer and execute custom SQL statements. SqlSession allows you to start a session before executing SQL statements. Transaction operations are involved, so there are commit, rollback, close, and so on. This is also an application of the template design pattern.

For example, SqlSession controls database transactions as follows:

/ / define SqlSession
SqlSession sqlSession = null;
try {
    // Open the SqlSession session
    sqlSession = SqlSessionFactory.openSession();
    // some code...
    sqlSession.commit();    // Commit the transaction
} catch (IOException e) {
    sqlSession.rollback();  // Rollback the transaction
}finally{
    // Ensure that the resource is closed successfully in the finally statement
    if(sqlSession ! =null){ sqlSession.close(); }}Copy the code

MapperProxy

MapperProxy is the key object of Mapper mapping SQL statements. The Dao layer or Mapper layer we write is bound to the corresponding SQL statements through MapperProxy.

This is the core binding process for MyBatis. We can see that SqlSession first calls the getMapper method. SqlSession is the eldest brother, only define standards (there is a saying, first-class enterprises do standards, second-rate enterprises do brands, third-rate enterprises do products)

SqlSession does not want to do things assigned to The Configuration hand, but Configuration also has a younger brother, it does not want to do things directly assigned to the younger brother, who is this younger brother? It’s called MapperRegistry, and we’re about to get to the heart of it. MapperRegistry is equivalent to the project manager, the project manager only from the general grasp of the project progress, do not need to know how his younger brother is working, to complete the task. Finally, the MapperProxyFactory does the real work. If you don’t have the code proxy. newProxyInstance, I suggest you take a look at this article, Proxy Patterns series 6.

In other words, the binding of Mapper and SQL statements in MyBatis is done by dynamic proxy.

MapperProxyFactory generates a proxy object, which is MapperProxy, and finally invokes the mapperMethod.execute method. Execute logic is relatively simple, which is to determine whether to insert, update, delete or query statements.

MapperProxyFactory, MapperProxy, MapperProxy, MapperProxy, MapperProxy, MapperProxy The end result is the logic in Executor.

Executor

Each SqlSession has an Executor object, which is responsible for adding, deleting, modifying, and querying. It can be interpreted as a encapsulated version of a JDBC Statement. An Executor is an Executor, and the Executor is an Executor.

The creation type of the actuator is configured via the MyBatis XML file:

<settings> <! -- SIMPLE, REUSE, BATCH --> <setting name="defaultExecutorType" value="SIMPLE"/>
</settings>
Copy the code

The different actuators are described as follows:

  • SimpleExecutor : The Statement object is the default executable used in MyBatis. The Statement object is opened every time an update or select is executed. Close the Statement object (either a Statement or a PreparedStatment object)
  • ReuseExecutor : The reusable executor, by reuse, means the reuse of the Statement. It uses an internal Map to cache all created statements. Each time a SQL command is executed, it checks whether a Statement object based on the SQL Statement exists. If a Statement object exists and the connection has not been closed, continue to use the previous Statement object and cache it. Since every SqlSession has a new Executor object, the Statement scope cached on ReuseExecutor is the same SqlSession.
  • BatchExecutor: BatchExecutor used to output multiple SQL to the database at once
  • CachingExecutor: a cache executor that queries results from the cache and returns the previous results if they exist. If not, delegate to an Executor delegate from the database. The delegate can be any of the above.

Executor execution:

The Executor completes its work, and the Executor passes the rest of the work to the StatementHandler. Let’s get to know StatementHandler

Once the interface is found through MapperProxy, the specific logic is executed through Executor, which is then handed over to StatementHandler.

StatementHandler

StatementHandler is the most important of the four components. It is responsible for manipulating Statement objects and interacting with the database. It also uses ParameterHandler and ResultSetHandler to map parameters. Bind the result to an entity class.

StatementHandler’s inheritance structure:

  • SimpleStatementHandler: Manages Statement objects and pushes SQL statements to the database that do not require precompilation.
  • PreparedStatementHandler: management Statement object and to the data needed to push a precompiled SQL Statement.
  • CallableStatementHandler: Manages the Statement object and calls stored procedures in the database.

MyBatis will create a StatementHandler based on the type of SQL statement. After creating a PreparedStatement, ParameterHandler will be used to process parameters.

ParameterHandler

ParameterHandler is a ParameterHandler that dynamically assigns values to SQL statements in a PreparedStatement. It implements these two methods:

  • GetParameterObject: Reads parameters
  • SetParameters: Used to assign values to parameters in a PreparedStatement

ResultSetHandler

MyBatis only has one default implementation class DefaultResultSetHandler. DefaultResultSetHandler handles two things:

  • Process the result set generated after the Statement is executed and generate a result list
  • Handles the output parameters of the stored procedure after execution

The result map is processed in DefaultResultSetHandler and the above structure is returned to the calling client to complete the execution of a complete SQL statement.

MyBatis SQL execution of the whole process summary

  1. Generate the source from the MyBatis XML configuration file
  2. Generate Executor and SqlSessionFactoryBuilder from the data in source
  3. SqlSessionFactory is obtained by SqlSessionFactoryBuilder
  4. Get the SqlSession by SqlSessionFactory
  5. Get MapperProxyFactory from SqlSession
  6. Get MapperProxy by using MapperProxyFactory
  7. Use MapperProxy to operate specific SQL interfaces
  8. The execution logic of the SQL interface is handed over to Executor (which has already been generated by configuration)
  9. The Executor execution logic is handed over to the StatementHandler
  10. StatementHandler will select one of SimpleStatementHandler, PreparedStatementHandler, or CallableStatementHandler according to the SQL type to execute the SQL. For example, PreparedStatementHandler
  11. Dynamically assign values to SQL statements through the ParameterHandler before data is processed in PreparedStatementHandler
  12. Continue processing SQL logic through StatementHandler
  13. After all SQL logic is processed, a result set is generated using ResultSetHandler and data is returned to the client

Afterword.

Through this article, you can initially understand the MyBatis logic of the whole picture, we can learn as a point of interest, but also as an interview test point. The feeling of MyBatis was still vague before, especially when I looked at the basic knowledge, there were a bunch of objects jumping around in it, and I always felt that I didn’t fully understand it. Now after all combing through, the whole process is much clearer.

This is the end of the explanation of the basic knowledge of MyBatis. In the future, I plan to write another article about the integration of MyBatis and Spring Boost, and then extract the knowledge used by Xiaomi in MyBatis project as the end of this series. I believe that after 2 weeks of study, the use of MyBatis related knowledge in the project will not become a bottleneck for me to see the code and development.

Reference blog: mp.weixin.qq.com/s?__biz=Mzk…

Welcome everyone to like a lot, more articles, please pay attention to the wechat public number “Lou Zai advanced road”, point attention, do not get lost ~~