Understanding How MyBatis‑Plus Maps Mapper Methods to SQL Statements and Executes Database Operations
This article provides a detailed walkthrough of MyBatis‑Plus internals, covering the auto‑configuration of SqlSessionFactory, parsing of mapper XML and annotations, registration of mapper interfaces via @MapperScan, creation of dynamic proxies, and the final assembly of executable SQL scripts for database interactions.
MyBatis‑Plus is an enhancement built on top of MyBatis that eliminates XML configuration by automatically mapping Mapper interface methods to SQL statements, adding features such as optimistic locking, pagination, and automatic field filling.
The process starts with MybatisPlusAutoConfiguration where the sqlSessionFactory() method creates a MybatisSqlSessionFactoryBean instance, injects components like the primary key generator, SQL injector, and meta‑object handler, and finally obtains the SqlSessionFactory via MybatisSqlSessionFactoryBean#getObject() :
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
factory.setDataSource(dataSource);
// ... inject plugins, global config, etc.
return factory.getObject();
}When the factory builds the session, MybatisXMLConfigBuilder#parse() parses the XML configuration and mapper files. Inside it, mapperElement() iterates over each Mapper interface, calling configuration.addMapper(mapper) which ultimately invokes MybatisMapperRegistry#addMapper() and MybatisMapperAnnotationBuilder#parse() to process @Select , @Update , etc.
private void mapperElement(XNode parent) throws Exception {
// collect resources and mapper classes
for (String resource : resources) {
XMLMapperBuilder mapperParser = new XMLMapperBuilder(...);
mapperParser.parse();
}
for (Class
mapper : mapperClasses) {
configuration.addMapper(mapper);
}
}Spring scans mapper interfaces via @MapperScan , which registers a MapperScannerConfigurer . This class implements BeanDefinitionRegistryPostProcessor and replaces each mapper bean definition with a MapperFactoryBean that produces the actual mapper proxy.
definition.setBeanClass(this.mapperFactoryBeanClass);
definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName);When a mapper is autowired, MapperFactoryBean#getObject() calls sqlSessionTemplate.getMapper() , which retrieves a MybatisMapperProxy created by MybatisMapperProxyFactory#newInstance() . The proxy’s invoke() method distinguishes Object methods, default methods, and mapper methods, delegating the latter to a cached MybatisMapperMethod that finally executes the assembled SQL.
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
}
final MybatisMapperMethod mapperMethod = cachedMapperMethod(method);
return mapperMethod.execute(sqlSession, args);
}The generated SQL is a dynamic <script> block that uses MyBatis’s choose , when , and if tags to conditionally include clauses based on the provided Wrapper or entity fields, for example:
<script>
SELECT
<choose>
<when test="ew != null and ew.sqlSelect != null">${ew.sqlSelect}</when>
<otherwise>id,name,type</otherwise>
</choose>
FROM node
<if test="ew != null">
<where>
<if test="ew.entity.id != null">id=#{ew.entity.id}</if>
<if test="ew.entity['name'] != null">AND name=#{ew.entity.name}</if>
<!-- more dynamic conditions -->
</where>
</if>
</script>Through this chain—from auto‑configuration, XML parsing, mapper registration, dynamic proxy creation, to SQL script generation—MyBatis‑Plus seamlessly translates Java mapper methods into efficient database operations without requiring explicit XML mappings.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.