首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

MyBatis Generator 定制化實戰:繼承擴展實現專屬代碼生成模板

     編輯:Java 綜合教學

MyBatis Generator 定制化實戰:繼承擴展實現專屬代碼生成模板

MyBatis Generator (MBG) 內置的 targetRuntime (MyBatis3/MyBatis3Simple 等) 常無法滿足項目特定需求(如統一基類、自定義查詢方法、特殊註解、Oracle Schema 處理)。本文通過**繼承核心類 + 覆寫關鍵方法 + 配置 targetRuntime** 的非侵入式方式,實現完全可控的代碼生成定制化。

架構設計:四層擴展鏈路

IntrospectedTable (表元數據解析)
    ↓ create/calculate
JavaClientGenerator (Mapper 接口生成) ← XMLMapperGenerator (XML 映射生成)
    ↓ generate
CompilationUnit (Java 文件) / XmlElement (XML 文件)
    ↓ 生成具體方法元素
AbstractJavaMapperMethodGenerator / AbstractXmlElementGenerator

步驟一:自定義 IntrospectedTable (核心入口)

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();
    }
}

步驟二:自定義 XMLMapperGenerator (控制 SQL 映射)

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);
        }
    }
}

步驟三:自定義具體 SQL 元素生成器 (selectAll 實現)

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);
    }
}

步驟四:自定義 JavaMapperGenerator (同步 Mapper 接口)

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);
        }
    }
}

步驟五:Generator 配置文件接入

<?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>

Maven 執行命令


需求擴展點實現提示


統一 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% 可控的代碼生成,這才是框架擴展的正確姿勢。」

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved