MyBatis Generator (MBG),寫擴(kuò)展類,以適應(yīng) MySQL 大小寫敏感配置的各種情況、適應(yīng)分表時(shí)動(dòng)態(tài)替換表名

項(xiàng)目地址:https://github.com/uncleAndyChen/mybatis-generator/tree/master/mybatis-generator-enhance

運(yùn)行本工程生成表配置內(nèi)容,一定要連接參數(shù)lower_case_table_names配置為0或者2的數(shù)據(jù)庫服務(wù)器,并且是配置為0或者2之后才創(chuàng)建的數(shù)據(jù)表,否則,生成的表配置內(nèi)容的表名,全是小寫的,并非駝峰式命名法。表配置內(nèi)容生成好之后,重新生成 mapper 時(shí)連接的數(shù)據(jù)庫服務(wù)器的lower_case_table_names配置值,對生成結(jié)果沒有影響。

本文對應(yīng)的完整項(xiàng)目

進(jìn)入以上項(xiàng)目路徑可查看更詳細(xì)的介紹。

本擴(kuò)展的作用

2019-06-19 更新

  1. 生成的*Mapper.xml文件中的腳本,表名取MBG所需配置文件中配置的值(工程中的配置文件是:generatorConfig.xml),而不是從數(shù)據(jù)庫讀取到的值。
    • 如果數(shù)據(jù)庫表名采用下劃線命名法,請忽略這個(gè)作用。
    • 數(shù)據(jù)庫表名、字段名命名法:
      • 之前本人推薦采用駝峰命名法。
        • 想要保持統(tǒng)一的命名規(guī)則。
        • 不知道通過配置的方式兼顧兩種命名法,即數(shù)據(jù)庫表名、字段名在采用下劃線命名法的情況下,通過 MBG 生成的對應(yīng)每一個(gè)表的 POJO 采用駝峰命名法,查詢數(shù)據(jù)時(shí)不需要考慮 MBG 生成的 xml 映射文件中的 resultMap,如 parent_id 與 parentId 的映射。
      • 現(xiàn)在推薦下劃線命名法。
        • 這是為了避免因 windows 與 linux 以及云數(shù)據(jù)庫的大小寫敏感不一致,從而帶來不必要的麻煩。
        • 同時(shí)也是考慮到絕大多數(shù)同行的習(xí)慣。
        • 最主要的,是解決了之前不知道的兼顧兩種命名法的辦法(好象有一點(diǎn)拗口~~)
  2. 給表名添加MySQL“邊界”,用 `(左上角數(shù)字鍵1左邊、Tab鍵上邊、Esc鍵下邊的鍵)引起來。目的是分表時(shí)進(jìn)行表名替換,把每張個(gè)表的表名當(dāng)作一個(gè)整體,避免表名補(bǔ)充部分替換。

解決兩個(gè)問題

  1. 適應(yīng)lower_case_table_names的三種配置值。
  2. 利用MyBatis插件,根據(jù)業(yè)務(wù)規(guī)則,對表名進(jìn)行動(dòng)態(tài)替換。

自己擴(kuò)展的好處

  1. 比起直接修改MBG源代碼,這種方式對MBG無代碼侵入,方便將來升級MBG。
  2. 符合面向?qū)ο笤O(shè)計(jì)的【開閉原則】,即通過增加代碼來為軟件添加新功能,而不是直接修改原有代碼。這一點(diǎn),MBG做得非常好,除了可以非常方便的擴(kuò)展之外,還可以寫各種插件以實(shí)現(xiàn)自己的業(yè)務(wù)需要。

自己擴(kuò)展的好處

  1. 比起直接修改MBG源代碼,這種方式對MBG無代碼侵入,方便將來升級MBG。
  2. 符合面向?qū)ο笤O(shè)計(jì)的【開閉原則】,即通過增加代碼來為軟件添加新功能,而不是直接修改原有代碼。這一點(diǎn),MBG做得非常好,除了可以非常方便的擴(kuò)展之外,還可以寫各種插件以實(shí)現(xiàn)自己的業(yè)務(wù)需要。

使用自己的擴(kuò)展類

在配置文件 generatorConfig.xmlcontext 節(jié)點(diǎn),配置 targetRuntime 值,指向自己的擴(kuò)展類,需要帶包名,如本例:

<context id="Mysql" targetRuntime="mybatis.generator.enhance.IntrospectedTableEnhanceImpl" defaultModelType="flat">

擴(kuò)展類的代碼很簡單,只有十幾行

import org.mybatis.generator.codegen.mybatis3.IntrospectedTableMyBatis3Impl;

public class IntrospectedTableEnhanceImpl extends IntrospectedTableMyBatis3Impl {
    @Override
    public String getFullyQualifiedTableNameAtRuntime() {
        return getTableNameFromConfigFile();
    }

    @Override
    public String getAliasedFullyQualifiedTableNameAtRuntime() {
        return getTableNameFromConfigFile();
    }

    private String getTableNameFromConfigFile() {
        String tableName = this.getTableConfiguration().getTableName();
        return "`" + tableName + "`";
    }
}

兩種運(yùn)行方式

以程序方式運(yùn)行

仿照官方的org.mybatis.generator.api.ShellRunner,寫一段代碼,以程序的方式運(yùn)行。本工程的代碼如下:

public class GeneratorEnhanceRun {
    public static void main(String[] args) {
        try {
            List<String> warnings = new ArrayList<String>();
            /**
             * 初始化配置解析器
             */
            ConfigurationParser cp = new ConfigurationParser(warnings);

            /**
             * 獲取配置文件信息
             */
            FileInputStream fileInputStream = new FileInputStream(ConfigProperties.getValue("configFile"));

            /**
             * 調(diào)用配置解析器創(chuàng)建配置對象
             */
            Configuration config = cp.parseConfiguration(fileInputStream);
            /**
             * shellcallback接口主要用來處理文件的創(chuàng)建和合并,傳入overwrite參數(shù);默認(rèn)的shellcallback是不支持文件合并的;
             */
            DefaultShellCallback callback = new DefaultShellCallback(true);
            /**
             * 創(chuàng)建一個(gè)MyBatisGenerator對象。MyBatisGenerator類是真正用來執(zhí)行生成動(dòng)作的類
             */
            MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
            /**
             * 用System.out打印執(zhí)行過程
             */
            ProgressCallback progressCallback = new VerboseProgressCallback();

            /**
             *  執(zhí)行生成操作
             */
            myBatisGenerator.generate(progressCallback);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

本工程,直接運(yùn)行GeneratorEnhanceRun下的main方法,在運(yùn)行之前需要先修改resources目錄下的配置文件application.properties,將MBG運(yùn)行需要的配置文件路徑配置對。

configFile=C:/workspace/mbg/mybatis-generator/generatorConfig.xml

cmd窗口運(yùn)行jar文件

  • 下MBG的jar包,傳送門,解壓,找到mybatis-generator-1.3.7.jar備用。
  • 將本模塊生成jar文件,生成的jar文件名mybatis-generator-enhance.jar。
  • 將兩個(gè)jar文件以及配置文件放到model與dal項(xiàng)目所在的目錄下,在 cmd 窗口執(zhí)行:
java -Dfile.encoding=UTF-8 -cp mybatis-generator-1.3.7.jar;mybatis-generator-enhance.jar org.mybatis.generator.api.ShellRunner -configfile generatorConfig.xml -overwrite

這里通過 -cp 指定需要用到的所有jar包,用分號隔開,這樣在運(yùn)行的時(shí)候才能找到相應(yīng)的類。

原理

簡單的說,就是自己的實(shí)現(xiàn)類IntrospectedTableEnhanceImpl繼承自MBG的一個(gè)具體實(shí)現(xiàn)類,重寫獲取表名的方法。

IntrospectedTable是MBG提供的一個(gè)比較基礎(chǔ)的擴(kuò)展類,相當(dāng)于可以重新定義一個(gè)runtime。如果要通過繼承IntrospectedTable完成擴(kuò)展,需要自己來實(shí)現(xiàn)生成XML和Java代碼的所有代碼,也可以直接繼承IntrospectedTableMyBatis3Impl,重寫自己需要的業(yè)務(wù)邏輯,本模塊就是直接繼承自該類。

要擴(kuò)展自己的業(yè)務(wù)邏輯,建議先仔細(xì)閱讀IntrospectedTableMyBatis3Impl和IntrospectedTableMyBatis3SimpleImpl,這兩個(gè)類用得多一些。

在MBG中,提供了幾種默認(rèn)的IntrospectedTable的實(shí)現(xiàn),其實(shí)在context上設(shè)置的runtime對應(yīng)的就是不同的IntrospectedTable的實(shí)現(xiàn),下面是幾種runtime和對應(yīng)的實(shí)現(xiàn)類:

  • MyBatis3 (default):org.mybatis.generator.codegen.mybatis3.IntrospectedTableMyBatis3Impl
  • MyBatis3Simple:org.mybatis.generator.codegen.mybatis3.IntrospectedTableMyBatis3SimpleImpl
  • Ibatis2Java2:org.mybatis.generator.codegen.ibatis2.IntrospectedTableIbatis2Java2Impl
  • Ibatis2Java5:org.mybatis.generator.codegen.ibatis2.IntrospectedTableIbatis2Java5Impl

MySQL 數(shù)據(jù)庫驅(qū)動(dòng)版本與數(shù)據(jù)庫版本問題

用高版本的數(shù)據(jù)庫驅(qū)動(dòng)mysql-connector-java 8.0.13連接低版本數(shù)據(jù)庫MySQL 5.7.23,會(huì)有以下問題:

  1. 報(bào)錯(cuò)
    Cannot obtain primary key information from the database, generated objects may be incomplete
    ...
    
  2. 生成的 mapper 缺少以下接口:
    deleteByPrimaryKey
    selectByPrimaryKey
    updateByPrimaryKeySelective
    updateByPrimaryKey
    

解決

數(shù)據(jù)庫驅(qū)動(dòng)與數(shù)據(jù)庫版本匹配即可,作者在以下兩個(gè)版本(5.x與8.x)測試通過:

  1. 數(shù)據(jù)庫驅(qū)動(dòng)mysql-connector-java 8.0.13連接數(shù)據(jù)庫MySQL 8.0.11,對應(yīng)driverClassName: com.mysql.cj.jdbc.Driver
  2. 數(shù)據(jù)庫驅(qū)動(dòng)mysql-connector-java 5.1.29連接數(shù)據(jù)庫MySQL 5.7.23,對應(yīng)driverClassName: com.mysql.jdbc.Driver

本工程的數(shù)據(jù)庫驅(qū)動(dòng)版本,使用的是當(dāng)前最新的mysql-connector-java 8.0.13,僅支持連接高版本MySQL 8.x。

如果要在MySQL 5.7.x下運(yùn)行,只需要修改以下兩個(gè)地方(注意是5.7.x,其它5.x版本沒測試):

  1. 修改pom.xml中mysql-connector.version,改為低版本5.1.39。
  2. 本項(xiàng)目的執(zhí)行,依賴根目錄下的generatorConfig.xml文件,將其中driverClass,由com.mysql.cj.jdbc.Driver改為com.mysql.jdbc.Driver。

關(guān)于作者

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. 簡介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存儲過程以及高級映射的優(yōu)秀的...
    笨鳥慢飛閱讀 6,246評論 0 4
  • ORA-00001: 違反唯一約束條件 (.) 錯(cuò)誤說明:當(dāng)在唯一索引所對應(yīng)的列上鍵入重復(fù)值時(shí),會(huì)觸發(fā)此異常。 O...
    我想起個(gè)好名字閱讀 5,973評論 0 9
  • 1、引言 數(shù)據(jù)庫設(shè)計(jì)過程中表、字段等的命名規(guī)范也算是設(shè)計(jì)規(guī)范的一部分,不過設(shè)計(jì)規(guī)范更多的是為了確保數(shù)據(jù)庫設(shè)計(jì)的合理...
    SnowflakeCloud閱讀 41,254評論 0 48
  • 積攢了一年多的加班,終于在離職檔期兌現(xiàn)為一個(gè)多月的調(diào)休,很多同事都說真好啊,可以利用這一個(gè)多月好好去面試呢,其實(shí)我...
    尋葉亭閱讀 1,309評論 0 3
  • 芮:媽媽我再也不惹你生氣了 媽媽:真的嗎 芮:是真的 媽媽:再惹我生氣怎么辦 芮:我真的不會(huì)了 對視幾秒之后,芮小...
    讀讀寫寫蕭十一閱讀 131評論 0 0

友情鏈接更多精彩內(nèi)容