MyBatis Generator (MBG) 內置的 targetRuntime (MyBatis3/MyBatis3Simple 等) 常無法滿足項目特定需求(如統一基類、自定義查詢方法、特殊註解、Oracle Schema 處理)。本文通過**繼承核心類 + 覆寫關鍵方法 + 配置 targetRuntime** 的非侵入式方式,實現完全可控的代碼生成定制化。
IntrospectedTable (表元數據解析)
↓ create/calculate
JavaClientGenerator (Mapper 接口生成) ← XMLMapperGenerator (XML 映射生成)
↓ generate
CompilationUnit (Java 文件) / XmlElement (XML 文件)
↓ 生成具體方法元素
AbstractJavaMapperMethodGenerator / AbstractXmlElementGenerator
public class InsoIntrospectedTable extends IntrospectedTableMyBatis3Impl {
// 1. 指定自定義 XML 生成器
@Override
protected void calculateXmlMapperGenerator(AbstractJavaClientGenerator javaClientGenerator,
List warnings, ProgressCallback callback) {
// 原邏輯:根據 javaClientGenerator 類型選擇 XML 生成器
// 定制:強制使用我們的 InsoXMLMapperGenerator
xmlMapperGenerator = new InsoXMLMapperGenerator();
initializeAbstractGenerator(xmlMapperGenerator, warnings, callback);
}
// 2. 指定自定義 Mapper 接口生成器
@Override
protected AbstractJavaClientGenerator createJavaClientGenerator() {
if (context.getJavaClientGeneratorConfiguration() == null) return null;
// 原邏輯:根據配置類型實例化不同生成器
// 定制:強制使用我們的 InsoJavaMapperGenerator
return new InsoJavaMapperGenerator();
}
}
public class InsoXMLMapperGenerator extends XMLMapperGenerator {
@Override
protected XmlElement getSqlMapElement() {
XmlElement answer = new XmlElement("mapper");
answer.addAttribute(new Attribute("namespace", introspectedTable.getMyBatis3SqlMapNamespace()));
context.getCommentGenerator().addRootComment(answer);
// 1. 基礎 ResultMap / ColumnList / WhereClause
addResultMapWithoutBLOBsElement(answer);
addResultMapWithBLOBsElement(answer);
addExampleWhereClauseElement(answer);
addBaseColumnListElement(answer);
addBlobColumnListElement(answer);
// 2. 保留需要的標準 CRUD
addSelectByPrimaryKeyElement(answer);
addInsertElement(answer);
addInsertSelectiveElement(answer);
addUpdateByPrimaryKeySelectiveElement(answer);
addUpdateByPrimaryKeyWithBLOBsElement(answer);
addDeleteByPrimaryKeyElement(answer);
// 移除 Example 相關:addSelectByExample... addUpdateByExample... addDeleteByExample...
// 3. 【核心定制】添加自定義 selectAll 方法
addSimpleSelectAllElement(answer);
return answer;
}
protected void addSimpleSelectAllElement(XmlElement parentElement) {
if (introspectedTable.getRules().generateSelectByPrimaryKey()) {
AbstractXmlElementGenerator generator = new InsoSelectAllElementGenerator();
initializeAndExecuteGenerator(generator, parentElement);
}
}
}
public class InsoSelectAllElementGenerator extends AbstractXmlElementGenerator {
@Override
public void addElements(XmlElement parentElement) {
XmlElement select = new XmlElement("select");
select.addAttribute(new Attribute("id", "selectAll"));
select.addAttribute(new Attribute("resultMap", "BaseResultMap"));
select.addElement(new TextElement("select "));
select.addElement(getBaseColumnListElement());
select.addElement(new TextElement("from "));
select.addElement(getTableNameElement());
parentElement.addElement(select);
}
}
public class InsoJavaMapperGenerator extends JavaMapperGenerator {
@Override
public List getCompilationUnits() {
Interface interfaze = new Interface(new FullyQualifiedJavaType(
introspectedTable.getMyBatis3JavaMapperType()));
interfaze.setVisibility(JavaVisibility.PUBLIC);
// ... 標準註解、導入、父接口配置 ...
// 標準方法 (保留需要的)
addSelectByPrimaryKeyMethod(interfaze);
addInsertMethod(interfaze);
addInsertSelectiveMethod(interfaze);
addUpdateByPrimaryKeySelectiveMethod(interfaze);
addUpdateByPrimaryKeyWithBLOBsMethod(interfaze);
addDeleteByPrimaryKeyMethod(interfaze);
// 移除 Example 方法
// 【核心定制】添加 selectAll 方法
addSelectAllMethod(interfaze);
return Collections.singletonList(interfaze);
}
protected void addSelectAllMethod(Interface interfaze) {
if (introspectedTable.getRules().generateSelectByPrimaryKey()) {
AbstractJavaMapperMethodGenerator generator = new SelectAllMethodGenerator();
initializeAndExecuteGenerator(generator, interfaze);
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"https://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="default"
targetRuntime="com.xxcomp.core.generator.codegen.InsoIntrospectedTable"
defaultModelType="flat">
<!-- 插件增強 -->
<plugin type="org.mybatis.generator.plugins.ToStringPlugin"/>
<plugin type="org.mybatis.generator.plugins.EqualsHashCodePlugin"/>
<plugin type="com.xxcomp.core.generator.plugin.MapperPlugin">
<property name="targetProject" value="../inso-sys-service/src/main/java"/>
<property name="targetPackage" value="com.xxcomp.dao.generator"/>
</plugin>
<commentGenerator>
<property name="suppressDate" value="true"/>
</commentGenerator>
<jdbcConnection driverClass="oracle.jdbc.driver.OracleDriver"
connectionURL="jdbc:oracle:thin:@192.168.1.19:1521:EEMS"
userId="TEST" password="TEST"/>
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<javaModelGenerator targetPackage="com.xxcomp.model.generator"
targetProject="../inso-sys-api/src/main/java">
<property name="constructorBased" value="false"/>
<property name="useActualColumnNames" value="true"/>
<property name="rootClass" value="com.xxcomp.core.base.BaseModel"/>
</javaModelGenerator>
<sqlMapGenerator targetPackage="mappers.generator"
targetProject="../inso-sys-service/src/main/resources">
<property name="enableSubPackages" value="false"/>
</sqlMapGenerator>
<javaClientGenerator targetPackage="com.xxcomp.dao.generator"
targetProject="../inso-sys-service/src/main/java" type="XMLMAPPER">
<property name="rootInterface" value="com.xxcomp.core.base.BaseMapper"/>
</javaClientGenerator>
<!-- 關鍵配置 -->
<table tableName="SYS_%" catalog="INSO" schema="INSO"
enableCountByExample="false" enableUpdateByExample="false"
enableDeleteByExample="false" enableSelectByExample="false"
selectByExampleQueryId="false">
<!-- Oracle 不生成 schema 前綴 -->
<property name="ignoreQualifiersAtRuntime" value="true"/>
</table>
</context>
</generatorConfiguration>
需求 擴展點 實現提示 統一 BaseEntity (id、createTime、updateTime、version) Model 生成器 繼承 JavaModelGenerator,重寫addFields()注入公共字段自定義註解 (@TableName、@Data、@Builder) Model/Mapper 生成器 在 addClassAnnotations()/addInterfaceAnnotations()添加複雜查詢方法 (分頁、動態 SQL、多表 Join) XML/Mapper 方法生成器 編寫專屬 AbstractXmlElementGenerator/AbstractJavaMapperMethodGenerator多模塊生成 (API/Service/Dao 分離) 配置文件 + 插件 MapStruct 插件生成 Mapper,MBG 僅生成 Model + XML 「MBG 定制化的本質是『模板方法模式 + 策略模式』的框架級應用。通過繼承核心類並覆寫『工廠方法』與『模板步驟』,在不修改 MBG 源碼前提下實現 100% 可控的代碼生成,這才是框架擴展的正確姿勢。」