start

Time is limited, ability is limited, if there is an incorrect place, welcome to correct.

Speaking of MyBtis-Plus, to understand its source code, you need to know what MyBtis-Plus does in your project. The framework is easy to use, simple, and popular, so here’s a copy of its features from the myBtis-Plus introduction.

  • Non-invasive: only enhanced but not changed, introducing it will not affect the existing engineering, as smooth as silk
  • Small loss: the basic CURD will be automatically injected when started, the performance is basically loss-free, and the operation is directly object-oriented
  • Powerful CRUD operations: The built-in universal Mapper and universal Service can realize most CRUD operations of a single table with only a few configurations. There is a powerful conditional constructor to meet various requirements
  • Support for calls in the form of Lambda: by using Lambda expressions, it is convenient to write all kinds of query conditions, without worrying about field error
  • Support for automatic generation of primary keys: support up to four primary key policies (including distributed unique ID generator – Sequence), configurable, perfect to solve the primary key problem
  • Support for ActiveRecord mode: Support for ActiveRecord mode invocation, entity classes only need to inherit Model class to perform powerful CRUD operations
  • Support for custom global generic operations: Support for global generic method injection (Write once, use Anywhere)
  • Built-in code generator: Use code or Maven plug-in to quickly generate Mapper, Model, Service, Controller layer code, support template engine, and more custom configuration for you to use
  • Built-in pagination plugin: Based on MyBatis physical pagination, developers do not need to care about the specific operation, after configuring the plugin, write pagination is equivalent to normal List query
  • Paging plugin supports multiple databases: support MySQL, MariaDB, Oracle, DB2, H2, HSQL, SQLite, Postgre, SQLServer and other databases
  • Built-in performance analysis plug-in: output Sql statements and their execution time. It is recommended to enable this function when developing tests to quickly catch slow queries
  • Built-in global interception plug-in: Provides intelligent analysis and block of delete and UPDATE operations in all tables. You can also customize interception rules to prevent misoperations

In summary, Mybatis-Plus did three things in the project.

  1. Code generator.
  2. Startup time operations (database configuration, Mapper scanning, etc.).
  3. CRUD operations in the project.

Here’s a look at how Mybatis-Plus works at startup and during CRUD in a project.

At the start

If you want the configuration to take effect automatically when the project starts, you need to know how to write a SpringBoot Starter and have written one yourself before. There is a meta-INF folder under the Resources folder of myBatis -plus-boot-starter

  • additional-spring-configuration-metadata.jsonThis is used to prompt when we write Mybatis — plus related configuration in properties or yML files.
  • spring.factoriesAutomatic configuration is performed when the project starts. The automatic startup class configured inside# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoCon figuration

MybatisPlusAutoConfiguration

@Configuration

@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})// The system has the specified class

@ConditionalOnSingleCandidate(DataSource.class)// There is only one specified Bean in the container, or this Bean is the preferred Bean

@EnableConfigurationProperties(MybatisPlusProperties.class)// Provide support for beans with @ConfigurationProperties annotation

@AutoConfigureAfter(DataSourceAutoConfiguration.class)// Load one configuration class after another

public class MybatisPlusAutoConfiguration implements InitializingBean {

Copy the code

This class, because it implements the InitializingBean interface, gets the afterPropertiesSet method, which is automatically invoked after the Bean is initialized. There are also three methods annotated with @ConditionalonMissingBean.

This method creates beans by SpringBoot when SqlSessionFactory is not configured and saves them to the container.



This method creates beans by SpringBoot when the SqlSessionTemplate is not configured and saves them to the container.

This method is not configuredMapperFactoryBeanBeans are created by SpringBoot and stored in the container.

A method into com. Baomidou. Mybatisplus. Autoconfigure. MybatisPlusAutoConfiguration# sqlSessionFactory there is one MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();

MybatisSqlSessionFactoryBean

This class implements three interfacesFactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent>

  1. FactoryBean: Indicates that factory mode is used
  2. InitializingBean:afterPropertiesSetCalled when the property is set (when the Bean is created)
  3. ApplicationListenerIt’s a listener. It’s listening toApplicationContextInitialize or refresh events, which are called when initialized or refreshed. Parses all the unprocessed statement nodes in the cache. It is recommended to call this method once all the mappers are added as it provides fail-fast statement validation. To refreshMappedStatement

Then watchcom.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean#afterPropertiesSetThis method, in this method, is calledcom.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean#buildSqlSessionFactory

buildSqlSessionFactory

Simply create an SqlSessionFactory instance, but there’s a lot going on in this method.

  1. First parse the configuration of Mybatis.
  2. None Configuration Start related configurations
  3. Initialize the ID-work and print the Banner
  4. If the dbType is not configured, it is automatically obtained
  5. Custom enumeration class scan processing
  6. Scan alias package
  7. Add the interceptor plug-in
  8. If it is an XML configuration, parse the XML configuration file
  9. According to themapperLocationsparsingMapperfile
  10. And finally, createSqlSessionFactoryAnd return.

There is a problem here. The database type is set to Mysql in the configuration class, but it is still set to Other.

  @Bean

    public GlobalConfig globalConfig(a) {

        GlobalConfig conf = new GlobalConfig();

        DbConfig dbConfig = new DbConfig();

        dbConfig.setDbType(DbType.MYSQL);

        conf.setDbConfig(dbConfig);

        return conf;

    }

Copy the code

Because this object is new, it is not managed by Spring. If insteadResourceorAutowiredInjection, startup error.But it doesn’t matter, because it automatically determines the database type based on the Connection’s MetaData.

Now let’s look at this part of the method.That’s the one that mattersxmlMapperBuilder.parse();

thisparseMethod is used to parse an XML file.In the box, parse the interface file.



org.apache.ibatis.builder.annotation.MapperAnnotationBuilder#parseStatementIt is null, so it is not entered. This method is mainly used for parsingInsert,Select,Update,DeleteandSelectProvider,InsertProvider,UpdateProvider,DeleteProviderThe eight annotated methods, which are not in the project, are nullThe real injection is here

com.baomidou.mybatisplus.core.injector.AbstractSqlInjector#inspectInject this.getMethodList(mapperClass)The following injector is called

com.baomidou.mybatisplus.core.injector.DefaultSqlInjector#getMethodList

com.baomidou.mybatisplus.core.injector.AbstractMethod#inject

com.baomidou.mybatisplus.core.injector.AbstractMethod#injectMappedStatement Let’s do a deleteById,Mybatis-PlusHere’s the secret to automatically injecting basic CurdsOf course, there is one last checkorg.springframework.dao.support.DaoSupport org.mybatis.spring.mapper.MapperFactoryBean#checkDaoConfig

CRUD operations in the project

Used in projectsMybatis-PlusWith the exception of basic CRUD operations, SQL is mostly assembled using Lambda expressions.Mybatis-PlusAR mode, will not be discussed for the moment.

Let’s look at this from a simple query SQL,Mybatis-PlusHow the SQL is assembled.This is aMybatis-PlusUnit tests for the project

  • com.baomidou.mybatisplus.test.MybatisTest#test

This method is called

  • com.baomidou.mybatisplus.core.mapper.BaseMapper#selectCount

When it comes to Mybatis CRUD operations, there are two classes.

  • com.baomidou.mybatisplus.core.override.MybatisMapperProxy
  • com.baomidou.mybatisplus.core.override.MybatisMapperProxyFactory

MybatisMapperProxy implements the InvocationHandler interface and uses JDK dynamic proxy. While MybatisMapperProxyFactory this class all generated Mapper binding agent. In the org. Mybatis. Spring. SqlSessionTemplate# getMapper method is called for, is the JDK dynamic proxy class of production.

Breakpoint debugging

First get MapperGetting the proxy class



Access to SQL

  • com.baomidou.mybatisplus.core.conditions.AbstractWrapper#doIt
  • com.baomidou.mybatisplus.core.conditions.segments.MergeSegments#add
  • com.baomidou.mybatisplus.core.override.MybatisMapperMethod#MybatisMapperMethod
  • org.apache.ibatis.binding.MapperMethod.SqlCommand#SqlCommand
  • org.apache.ibatis.binding.MapperMethod.SqlCommand#resolveMappedStatement





As you can see, the query statement first concatenates the previous part and then dynamically concatenates the query criteria based on the lambda expression. So Mybatis-Plus is difficult to implement using lambda multi-table join queries.

In this methodorg.apache.ibatis.binding.MapperMethod.MethodSignature#MethodSignatureSet method signature.

Execute SQLcom.baomidou.mybatisplus.core.override.MybatisMapperMethod#execute maysqlSegmentAs the “”,columnMapTo null. Because when I break here, it’s all empty. (It’s not clear why.)

SQL Execution Process

Mybatis will createCacheKey each time it is queried. If the second query hits, it will go to cache. If the second query does not hit, it will go to basic query. And each query calls CachingExecutor first, and BaseExecutor after no cache hit.

  • org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
  • org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)
  • org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
  • org.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.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)
  • org.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)
  • org.apache.ibatis.executor.BaseExecutor#queryFromDatabase





conclusion

Why do you want to look at the source code? In fact, there are two reasons. One is to wonder why a BaseMapper can be used without basic CRUD. Second, it’s fun to write SQL for lambda expressions, and I want to see if I can modify it to support multiple table joins. Although it is Mybatis-Plus source code reading, in fact, there are most of Mybatis source code, read the source code does have a lot of benefits, at least now know how SQL injection, Mybatis level one cache is what, JDK dynamic proxy and so on. I also got a better understanding of Mybatis Plus.

If you want to support multiple table join queries, you need to add a new basic method, SQL statement only one SELECT, and then join leftJoin, rightJoin, join, on, using, union and other methods, from the table to parameters, all dynamically generated. It might work.

Although a lot of analysis, but this is only a general main process, many details have not been analyzed, there must be some missing places. Such as com. Baomidou. Mybatisplus. Core. Enums. SqlMethod. More knowledge or we go to find it together. Again, time is limited, capacity is limited, if there are mistakes, welcome to correct. Reprint please indicate.

This article was typeset using MDNICE