How Mybatis-Plus Enhances MyBatis: A Deep Dive into Its Core Implementation
This article explains how Mybatis-Plus extends MyBatis by injecting dynamic configuration XML, customizing mapper registration, and generating CRUD SQL statements through classes like MybatisSqlSessionFactoryBuilder, MybatisConfiguration, MybatisMapperRegistry, and various AbstractMethod implementations.
Mybatis-Plus (MP) is an enhancement tool for MyBatis that provides ready‑made CRUD methods, eliminating the need to write XML mappings.
Entry class: MybatisSqlSessionFactoryBuilder
MP injects its dynamic configuration XML into MyBatis during application startup via the MybatisSqlSessionFactoryBuilder#build method.
public class MybatisSqlSessionFactoryBuilder extends SqlSessionFactoryBuilder {
public SqlSessionFactory build(Configuration configuration) {
// ... omitted lines
if (globalConfig.isEnableSqlRunner()) {
new SqlRunnerInjector().inject(configuration);
}
// ... omitted lines
return sqlSessionFactory;
}
}MybatisConfiguration class
MP extends MyBatis’s Configuration, creates its own MybatisMapperRegistry, and overrides methods to register custom mappers and SQL statements.
public class MybatisConfiguration extends Configuration {
protected final MybatisMapperRegistry mybatisMapperRegistry = new MybatisMapperRegistry(this);
// ...
public MybatisConfiguration() {
super();
this.mapUnderscoreToCamelCase = true;
languageRegistry.setDefaultDriverClass(MybatisXMLLanguageDriver.class);
}
@Override
public void addMappedStatement(MappedStatement ms) {
// ...
}
@Override
public <T> void addMapper(Class<T> type) {
mybatisMapperRegistry.addMapper(type);
}
@Override
public void addMapper(Class<?> type) {
// use own MybatisMapperRegistry
}
}MybatisMapperRegistry
Replaces the default MapperAnnotationBuilder with MP’s MybatisMapperAnnotationBuilder.
public class MybatisMapperRegistry extends MapperRegistry {
@Override
public <T> void addMapper(Class<T> type) {
// ... omitted lines
MybatisMapperAnnotationBuilder parser = new MybatisMapperAnnotationBuilder(config, type);
parser.parse();
// ... omitted lines
}
}MybatisMapperAnnotationBuilder
Parses mapper interfaces, registers methods annotated with @Select, @Insert, etc., and injects default method list when the mapper is a SuperMapper child.
public class MybatisMapperAnnotationBuilder extends MapperAnnotationBuilder {
@Override
public void parse() {
// ... omitted lines
for (Method method : type.getMethods()) {
parseStatement(method);
InterceptorIgnoreHelper.initSqlParserInfoCache(cache, mapperName, method);
SqlParserHelper.initSqlParserInfoCache(mapperName, method);
}
if (GlobalConfigUtils.isSupperMapperChildren(configuration, type)) {
GlobalConfigUtils.getSqlInjector(configuration).inspectInject(assistant, type);
}
// ... omitted lines
}
@Override
public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) {
Class<?> modelClass = extractModelClass(mapperClass);
List<AbstractMethod> methodList = this.getMethodList(mapperClass);
TableInfo tableInfo = TableInfoHelper.initTableInfo(builderAssistant, modelClass);
methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass, tableInfo));
mapperRegistryCache.add(className);
}
}AbstractMethod implementations (example: SelectById)
Each concrete AbstractMethod builds the corresponding XML fragment and adds it to MyBatis’s MappedStatement.
/**
* Query a single record by ID
*/
public class SelectById extends AbstractMethod {
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
SqlMethod sqlMethod = SqlMethod.SELECT_BY_ID;
SqlSource sqlSource = new RawSqlSource(configuration,
String.format(sqlMethod.getSql(),
sqlSelectColumns(tableInfo, false),
tableInfo.getTableName(),
tableInfo.getKeyColumn(),
tableInfo.getKeyProperty(),
tableInfo.getLogicDeleteSql(true, true)),
Object.class);
return this.addSelectMappedStatementForTable(mapperClass, getMethod(sqlMethod), sqlSource, tableInfo);
}
}Overall, MP rewrites more than ten MyBatis classes to provide dynamic SQL capabilities. A simpler approach is to generate the XML resources and inject them via a custom SqlSessionFactoryBean implementation.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
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.
