Compare the update and insert return values of SIMPLE and BATCH of mybatis

Posted by anupamsaha on Thu, 25 Nov 2021 04:52:24 +0100

@RunWith(SpringRunner.class)
@SpringBootTest(classes = { AppServer.class })
@ActiveProfiles("mudev")
@ComponentScan(basePackages = "com.acca.pps")
@Import({SystemUtils.class})
@Slf4j
public class MybatisTest {
    
    @org.junit.Test
    public void executorTypeTest() {
        
        SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) SpringBeanFactoryUtils
                .getBean(SqlSessionFactory.class);
        
        AccuAirTestDao accuAirTestDao = (AccuAirTestDao) SpringBeanFactoryUtils
                .getBean(AccuAirTestDao.class);
        
        
        try(SqlSession session = sqlSessionFactory.openSession(ExecutorType.SIMPLE)) {
            
            String key1 = UUID.randomUUID().toString();
            String key2 = UUID.randomUUID().toString();
            
            AccuAirTestDao mapper = session.getMapper(AccuAirTestDao.class);
            System.out.println("insert================================");
            System.out.println(accuAirTestDao.insertTest(key1));
            System.out.println(mapper.insertTest(key2));
            System.out.println("insert================================");
            
            System.out.println("update================================");
            System.out.println(accuAirTestDao.updateTest(key1));
            System.out.println(mapper.updateTest(key2));
            System.out.println("update================================");
            
        } catch(Exception e) {
            
        }
    }
}

The above code can also enable mybatis to switch between different submission modes and obtain different sqlsessions.

 

Or when configuring the architecture, you can configure two different sqlsessiontemplates to scan different package name controls. You need to insert and update the return value, use the configuration of SIMPLE mode, and use the BATCH mode for BATCH insertion.

It can also be used as an interceptor, which is similar to paging. It is set to SIMPLE by default. If the suffix of the method name appears BATCH, it will be switched to the BATCH query mode.

Extension: reason for returning - 2147482646 in BATCH mode   This blog can be explained clearly. The blog address is:

To prevent loss, record as follows:

Preface: during the project demo a few days ago, I found a very strange phenomenon, that is, MyBatis found that the return value of update and insertion has always been "- 2147482646". No matter how to change it, this value has always been unchanged... It's confusing. Baidu and Google said this
It is caused by the defaultExecutorType setting. If it is set to BATCH, the update return value will be lost.
If the BATCH executor is in use, the update counts are being lost.
Operation: in other words, in the spring configuration file, just change the executorType in constructor Arg to SIMPLE (the previous value is BATCH, which will cause this problem) or comment it out directly
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
        <!-- Execution type -->
        <constructor-arg name="executorType" value="SIMPLE"></constructor-arg>
    </bean>

  Such a change really works, but why does it return this strange number? What's the reason behind this? This blog will study why this number is returned. Open our idea. It's time to track the source code again. Let's go:

1: Open the variable in the configuration file and see that the SqlSessionTemplate class has a construction parameter type ExecutorType, that is, the value we configured. What happens when it is BATCH?

2: Parameter of ExecutorType. Open this class and find that it is an enumeration type, that is, it has only three configured values, SIMPLE, RESUME and BATCH. In the configuration file, we can only configure one of the three

3: After the program is executed, it can be seen that the final operation is the insert method of SqlSession. Let's open the source code of this method:

        Reader config = Resources.getResourceAsReader("conf.xml");
        
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(config);
     
        SqlSession sqlSession = sessionFactory.openSession();
    
        String sql = "com.mlxs.mybatis.test.userMapper.insertUser";
int res= sqlSession.insert(sql, "1");//

4: SqlSession.insert() method:

public interface SqlSession extends Closeable {
  int insert(String var1);

int insert(String var1, Object var2);
}

SqlSession is an interface with an insert method. Let's take a look at the implementation class of this interface:

Generally, if there is no special configuration in the source code, the Default setting must be adopted. Let's take a look at the source code of DefaultSqlSession:

Find this.insert method again:

You can see that it calls this.update method, and then find an update method:

Seeing that it essentially calls the update method of the executor, let's click in to see the update method:

You can see that it is an interface, so you must find the implementation class:

Here we can see the clue. If the cache is not configured, BaseExecutor must be used. Then Batch is configured in the configuration file. There is no doubt that it must select the update method in the BatchExecutor class:

 

  This strange number came out here. You can see that it is a fixed return without any judgment logic... This proves that as long as your insert method configures batch in the configuration file, it must return this value!

5: When configured as simple, what is returned?

Based on the above experience, we can directly look at the simpleexecution method here:

Then look at StatementHandler:

I found the update method of simplestationhandler. You can see that it returns the number returned by statement.getUpdateCount, that is, the number of rows actually affected, so it is a normal value.

  Summary:

This blog records the process of source code tracking, which explains why this number is returned by configuring BATCH. In actual programming, you may encounter many strange problems. At this time, you should dare to turn to the source code. The answer must be in the source code in order to fundamentally know the cause of the problem.

Topics: Java Mybatis