Throw doubt

Mybatis- Plus does allow us to write a lot less repetitive code, which is very useful. One of the most convenient is that Mapper interface can inherit BaseMapper to obtain the function of adding, deleting, changing, and checking. So how is the underlying code of this function implemented?

The principle of native Mybatis configuration

After all, Mybatis- Plus is the enhancement of Mybatis, so Mybatis- Plus must be based on the original mechanism of Mybatis to expand, along this idea, we first understand a problem, is how the original mapper. XML file and the corresponding Mapper interface.

In Mybatis, there must be a corresponding configuration class. This class is MappedStatement. Finally, the MappedStatement object is added to the mappedStatements collection for management in the Configuration class. The source code is as follows:

public class Configuration {
    protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection");  

    public void addMappedStatement(MappedStatement ms) { mappedStatements.put(ms.getId(), ms); }}Copy the code

Suppose you have a mapper. XML file defined as follows:


      
<! DOCTYPEmapper 
PUBLIC "- / / mybatis.org//DTD Mapper / 3.0 / EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yehongzhi.mydemo.mapper.UserMapper">
    <select id="getUserList" resultType="com.yehongzhi.mydemo.model.User">
        select * from user
    </select>
</mapper>
Copy the code

Let’s use debug mode to verify:

Mybatis parses mapper. XML into a MappedStatement object for management. With this in mind, we can create mappedStatements according to specific rules and put them into the mappedStatements set. Then we can realize the function of Mybatis- Plus BaseMapper.

Mybatis-plus source code analysis

First find MybatisPlusAutoConfiguration configuration class, creates MybatisSqlSessionFactoryBean.

And set MybatisConfiguration as the configuration class.

MybatisConfiguration is an important class that initializes a mybatisMapperRegistry, useful later.

Public class MybatisConfiguration extends Configuration {/** * Mapper registration */ protected Final MybatisMapperRegistry mybatisMapperRegistry = new MybatisMapperRegistry(this); }Copy the code

When creating MybatisSqlSessionFactoryBean invokes the afterPropertiesSet () method to create a sqlSessionFactory.

@Override
public void afterPropertiesSet(a) throws Exception {
    notNull(dataSource, "Property 'dataSource' is required");
    state((configuration == null && configLocation == null) | |! (configuration ! =null&& configLocation ! =null),
          "Property 'configuration' and 'configLocation' can not specified with together");
    this.sqlSessionFactory = buildSqlSessionFactory();
}
Copy the code

The buildSqlSessionFactory() method then parses mapper’s XML file.

Then go further and look at the bindMapperForNamespace() method.

It is then parsed using the MapperAnnotationBuilder class.

We then do basic SQL injection in the parse() method:

The key lies in this SQL injector.

So the key here is AbstractMethod, which uses a template pattern.

public abstract class AbstractMethod implements Constants {

    protected Configuration configuration;
    protected LanguageDriver languageDriver;
    protected MapperBuilderAssistant builderAssistant;

    /** * inject custom methods */
    public void inject(MapperBuilderAssistant builderAssistant, Class
        mapperClass, Class
        modelClass, TableInfo tableInfo) {
        this.configuration = builderAssistant.getConfiguration();
        this.builderAssistant = builderAssistant;
        this.languageDriver = configuration.getDefaultScriptingLanguageInstance();
        /* Inject custom methods */
        injectMappedStatement(mapperClass, modelClass, tableInfo);
    }

    /** * Inject custom MappedStatement **@paramMapperClass Indicates a mapper interface@paramModelClass Mapper generic *@paramTableInfo Database table reflection information *@return MappedStatement
     */
    public abstract MappedStatement injectMappedStatement(Class
        mapperClass, Class
        modelClass, TableInfo tableInfo);
}
Copy the code

Using the template pattern, subclasses simply override the injectMappedStatement() method, and all of the above initialization is shared. There are many subclasses of AbstractMethod, so we can pick a representative one and infer other uses, such as Insert classes.

As you can see, the statement information template in BaseMapper comes from enumerating SqlMethod.

The end result is to convert the MappedStatement object, add the registration, and you have the methods for these CRUD operations.

conclusion

To summarize the process of loading BaseMapper:

  1. Initialize theMybatisConfigurationandmybatisMapperRegistry.
  2. Parse the Mapper class to get the AbstractMethod collection.
  3. traverseAbstractMethodCollection, and then call the respective implementationinjectMappedStatement()Method to inject SQL.
  4. Add the registrationMappedStatementObject.

Thank you very much for reading and I hope this article has been helpful and enlightening to you.

The article continues to update, wechat search “Java technology enthusiasts”, the first time after paying attention to the technical article push, article classification is collected on github: github.com/yehongzhi, you can always find what you are interested in

Please give me a thumbs-up if you think it is useful. Your thumbs-up is the biggest motivation for my creation

I’m a programmer who tries to be remembered. See you next time!!

Ability is limited, if there is any mistake or improper place, please criticize and correct, study together!