In this article, let’s talk about the executors of mybatis, and see how to use different executors in different scenarios and the implementation principle of different executors (based on mybatis 3.4.6).
Knowledge points
- What is an actuator
- Mybatis actuator type and when to use it
-
Implementation principle of each actuator
What is an actuator
As the name suggests, the executor is used to execute our SQL statements to get the results or update the database. It is a very core concept in mybatis. It provides basic operation interfaces such as addition, modification, query and transaction management. Basically, everything is carried out around the actuator. See the figure below
Mybatis actuator type and when to use it
Actuator type
Let’s first take a look at what types of actuators mybatis currently has
- SIMPLE
- REUSE
-
BATCH
At present, we can configure the above three kinds of actuators, and specify which one to use through defaultexecutortype (note that it is global). If it is configured through XML, refer to the official website
If spring boot integration is used, it is as follows
Let’s introduce the three actuators one by one.SIMPLE
It can be understood as a basic actuator, which is also the default actuator of mybatis and the most commonly used actuator. We don’t need to make any configuration changes. Its general process is: open connection – > SET statement – > parameter injection – > execution – > result mapping – > Close statement. You can see that the statement will be closed after each use.
REUSE
You can tell by name that this is a reusable actuator. What is reusable? It means that the first two steps in the simple process can be reused, that is, open connection – > SET statement. These two steps will create a new statement, and the reuse executor will maintain a cache internally. After the first acquisition, the statement will be cached with the corresponding SQL (placeholder? Not replaced by specific parameters) as the key, and the statement will not be closed, If you encounter this SQL later, just start from step 3, which brings performance optimization (in fact, the optimization is not large).
BATCH
It can also be seen from the name that this is a batch actuator. What does batch mean? In other words, it can execute a batch of SQL statements at one time, mainly for modification operations such as update and insert. For single or query operations, do not use this actuator. Why can it be executed in batch? In fact, it is in the SQL package
PreparedStatement
ofaddBatch()
, the principle will be explained in detail later.When to use
After knowing the characteristics of the three types of actuators, let’s compare the performance output in different scenarios, so that we can know when to use which type of actuator. There is no comparison here because the insertion operation essentially uses the update operation interface. Based on mybatis used by spring, it is based on the following table structure
single query
Code first
DefaultSqlSessionFactory sqlSessionFactory = (DefaultSqlSessionFactory)applicationContext.getBean("sqlSessionFactory"); //Choose the actuator type here DefaultSqlSession defaultSqlSession = (DefaultSqlSession)sqlSessionFactory.openSession(ExecutorType.SIMPLE); long startTime = System.currentTimeMillis(); // userInfoMapper.selectById(22222); defaultSqlSession.selectList("com.example.mybatisanalyze.mapper.UserInfoMapper.selectById", 22222); long endTime = System.currentTimeMillis(); System.out.println((endTime - startTime) + "ms");
simple:
As can be seen from the figure, it took 42ms
reuse:
takeDefaultSqlSession defaultSqlSession = (DefaultSqlSession)sqlSessionFactory.openSession(ExecutorType.SIMPLE);
Change toDefaultSqlSession defaultSqlSession = (DefaultSqlSession)sqlSessionFactory.openSession(ExecutorType.REUSE);
As can be seen from the figure, it took 34ms
batch:
takeDefaultSqlSession defaultSqlSession = (DefaultSqlSession)sqlSessionFactory.openSession(ExecutorType.SIMPLE);
Change toDefaultSqlSession defaultSqlSession = (DefaultSqlSession)sqlSessionFactory.openSession(ExecutorType.BATCH);
As can be seen from the figure, it took 43ms
Conclusion: the three actuators for single query are similar, but it is recommended to choose simple. See the description in actuator type for the reason.Single insert
Code first
DefaultSqlSessionFactory sqlSessionFactory = (DefaultSqlSessionFactory)applicationContext.getBean("sqlSessionFactory"); //The actuator type can be selected by yourself DefaultSqlSession defaultSqlSession = (DefaultSqlSession)sqlSessionFactory.openSession(ExecutorType.SIMPLE); long startTime = System.currentTimeMillis(); UserInfo userInfo = new UserInfo(); userInfo.setNickName("bbbcd"); userInfo.setUserName("abcdc"); userInfo.setBirthday(new Date()); userInfo.setRegisterTime(LocalDateTime.now()); userInfo.setEmail("12345"); defaultSqlSession.insert("com.example.mybatisanalyze.mapper.UserInfoMapper.insert", userInfo); long endTime = System.currentTimeMillis(); System.out.println((endTime - startTime) + "ms");
simple:
As can be seen from the picture, it took 172ms
reuse:
In codeDefaultSqlSession defaultSqlSession = (DefaultSqlSession)sqlSessionFactory.openSession(ExecutorType.SIMPLE)
Change this line toDefaultSqlSession defaultSqlSession = (DefaultSqlSession)sqlSessionFactory.openSession(ExecutorType.REUSE);
As can be seen from the figure, it took 178ms
batch:
In codeDefaultSqlSession defaultSqlSession = (DefaultSqlSession)sqlSessionFactory.openSession(ExecutorType.SIMPLE)
Change this line toDefaultSqlSession defaultSqlSession = (DefaultSqlSession)sqlSessionFactory.openSession(ExecutorType.BATCH);
As can be seen from the figure, it took 176ms
Conclusion: the performance of the three actuators is similar, so simple is recommendedBatch insert
Code first
DefaultSqlSessionFactory sqlSessionFactory = (DefaultSqlSessionFactory)applicationContext.getBean("sqlSessionFactory"); //Here, the actuator type can be selected by yourself DefaultSqlSession defaultSqlSession = (DefaultSqlSession)sqlSessionFactory.openSession(ExecutorType.SIMPLE); long startTime = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) { UserInfo userInfo = new UserInfo(); userInfo.setNickName("bbbc"); userInfo.setUserName("abcd"); userInfo.setBirthday(new Date()); userInfo.setRegisterTime(LocalDateTime.now()); userInfo.setEmail("1234"); defaultSqlSession.insert("com.example.mybatisanalyze.mapper.UserInfoMapper.insert", userInfo); } long endTime = System.currentTimeMillis(); System.out.println((endTime - startTime) + "ms");
Insert 10000 pieces of data
simple:
As can be seen from the figure, it took 11762ms
reuse:
In codeDefaultSqlSession defaultSqlSession = (DefaultSqlSession)sqlSessionFactory.openSession(ExecutorType.SIMPLE)
Change this line toDefaultSqlSession defaultSqlSession = (DefaultSqlSession)sqlSessionFactory.openSession(ExecutorType.REUSE);
As can be seen from the figure, it took 10992ms
batch:
In codeDefaultSqlSession defaultSqlSession = (DefaultSqlSession)sqlSessionFactory.openSession(ExecutorType.SIMPLE)
Change this line toDefaultSqlSession defaultSqlSession = (DefaultSqlSession)sqlSessionFactory.openSession(ExecutorType.BATCH);
And add a commit operation after the for loopdefaultSqlSession.commit();
As can be seen from the figure, it took 6173ms
Conclusion: obviously, batch should be selectedImplementation principle of each actuator
The logic related to mybatis and actuator is
org.apache.ibatis.executor
Bao Xia
Let’s take a look at the actuator interface firstorg.apache.ibatis.executor.Executor
Next, we can see the basic database operation system
You can see that the three actuators we use are subclasses, and two design patterns are used here, namelyBaseExecutor
Template patterns andCachingExecutor
Decorator mode implemented in. Let’s start at the entrance. The entrance isorg.apache.ibatis.session.defaults.DefaultSqlSession
, here we provide basic operations based onselectOne
Methods were analyzed untilorg.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
You will find that what he essentially calls is the query operation of the actuator
And where is this actuator generated? stayorg.apache.ibatis.session.defaults.DefaultSqlSessionFactory
We callopenSession
Method, we pass in the specified actuator type, or we can use the default, which will eventually beorg.apache.ibatis.session.Configuration#newExecutor(org.apache.ibatis.transaction.Transaction, org.apache.ibatis.session.ExecutorType)
Create actuators in
Here you can see that the corresponding actuator will be created according to the type of actuator passed in. Simple is used by default, andCachingExecutor
For a layer of packaging. Then, the query function above continues to analyze. We know that it will go to by defaultorg.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
The decorator mode is used here, and the L2 cache function is added to the original actuator function. In the end, it is calledorg.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
For execution, the first level cache is used here. If there is no cache, the database will be searched, that is, the method will be calledqueryFromDatabase
The template mode is used here,doQuery()
It is implemented by subclasses themselves. The logic of each subclass actuator is relatively simple. Let’s introduce it hereBatchExecutor
, others can see for themselves
It’s maintained herestatementList
andbatchResultList
The corresponding execution results are stored in the objectdoUpdate
It will be recorded at the end of the dayhandler.batch()
Call inPreparedStatement
ofaddBatch
Method, which is equivalent to temporarily storing instructions in the precompiler. We will call it later when we do commit ()doFlushStatements
Method to do batch execution.summary
There are still a lot of dry goods in this article. Basically, the executor of mybatis is introduced in detail and how to select the type. Of course, the bottom layer also involves some knowledge points of connection pool and SQL driver package. Later, the introduction of batch execution of SQL precompiler can be referred to https://blog.csdn.net/bluelin…