MyBatis Generator (MBG),写扩展类,以适应 MySQL 大小写敏感配置的各种情况、适应分表时动态替换表名

项目地址:https://github.com/uncleAndyChen/mybatis-generator/tree/master/mybatis-generator-enhance

运行本工程生成表配置内容,一定要连接参数lower_case_table_names配置为0或者2的数据库服务器,并且是配置为0或者2之后才创建的数据表,否则,生成的表配置内容的表名,全是小写的,并非驼峰式命名法。表配置内容生成好之后,重新生成 mapper 时连接的数据库服务器的lower_case_table_names配置值,对生成结果没有影响。

本文对应的完整项目

进入以上项目路径可查看更详细的介绍。

本扩展的作用

2019-06-19 更新

  1. 生成的*Mapper.xml文件中的脚本,表名取MBG所需配置文件中配置的值(工程中的配置文件是:generatorConfig.xml),而不是从数据库读取到的值。
    • 如果数据库表名采用下划线命名法,请忽略这个作用。
    • 数据库表名、字段名命名法:
      • 之前本人推荐采用驼峰命名法。
        • 想要保持统一的命名规则。
        • 不知道通过配置的方式兼顾两种命名法,即数据库表名、字段名在采用下划线命名法的情况下,通过 MBG 生成的对应每一个表的 POJO 采用驼峰命名法,查询数据时不需要考虑 MBG 生成的 xml 映射文件中的 resultMap,如 parent_id 与 parentId 的映射。
      • 现在推荐下划线命名法
        • 这是为了避免因 windows 与 linux 以及云数据库的大小写敏感不一致,从而带来不必要的麻烦。
        • 同时也是考虑到绝大多数同行的习惯。
        • 最主要的,是解决了之前不知道的兼顾两种命名法的办法(好象有一点拗口~~)
  2. 给表名添加MySQL“边界”,用 `(左上角数字键1左边、Tab键上边、Esc键下边的键)引起来。目的是分表时进行表名替换,把每张个表的表名当作一个整体,避免表名补充部分替换。

解决两个问题

  1. 适应lower_case_table_names的三种配置值。
  2. 利用MyBatis插件,根据业务规则,对表名进行动态替换。

自己扩展的好处

  1. 比起直接修改MBG源代码,这种方式对MBG无代码侵入,方便将来升级MBG。
  2. 符合面向对象设计的【开闭原则】,即通过增加代码来为软件添加新功能,而不是直接修改原有代码。这一点,MBG做得非常好,除了可以非常方便的扩展之外,还可以写各种插件以实现自己的业务需要。

自己扩展的好处

  1. 比起直接修改MBG源代码,这种方式对MBG无代码侵入,方便将来升级MBG。
  2. 符合面向对象设计的【开闭原则】,即通过增加代码来为软件添加新功能,而不是直接修改原有代码。这一点,MBG做得非常好,除了可以非常方便的扩展之外,还可以写各种插件以实现自己的业务需要。

使用自己的扩展类

在配置文件 generatorConfig.xmlcontext 节点,配置 targetRuntime 值,指向自己的扩展类,需要带包名,如本例:

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

扩展类的代码很简单,只有十几行

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 + "`";
    }
}

两种运行方式

以程序方式运行

仿照官方的org.mybatis.generator.api.ShellRunner,写一段代码,以程序的方式运行。本工程的代码如下:

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

            /**
             * 调用配置解析器创建配置对象
             */
            Configuration config = cp.parseConfiguration(fileInputStream);
            /**
             * shellcallback接口主要用来处理文件的创建和合并,传入overwrite参数;默认的shellcallback是不支持文件合并的;
             */
            DefaultShellCallback callback = new DefaultShellCallback(true);
            /**
             * 创建一个MyBatisGenerator对象。MyBatisGenerator类是真正用来执行生成动作的类
             */
            MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
            /**
             * 用System.out打印执行过程
             */
            ProgressCallback progressCallback = new VerboseProgressCallback();

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

本工程,直接运行GeneratorEnhanceRun下的main方法,在运行之前需要先修改resources目录下的配置文件application.properties,将MBG运行需要的配置文件路径配置对。

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

cmd窗口运行jar文件

  • 下MBG的jar包,传送门,解压,找到mybatis-generator-1.3.7.jar备用。
  • 将本模块生成jar文件,生成的jar文件名mybatis-generator-enhance.jar
  • 将两个jar文件以及配置文件放到model与dal项目所在的目录下,在 cmd 窗口执行:
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包,用分号隔开,这样在运行的时候才能找到相应的类。

原理

简单的说,就是自己的实现类IntrospectedTableEnhanceImpl继承自MBG的一个具体实现类,重写获取表名的方法。

IntrospectedTable是MBG提供的一个比较基础的扩展类,相当于可以重新定义一个runtime。如果要通过继承IntrospectedTable完成扩展,需要自己来实现生成XML和Java代码的所有代码,也可以直接继承IntrospectedTableMyBatis3Impl,重写自己需要的业务逻辑,本模块就是直接继承自该类。

要扩展自己的业务逻辑,建议先仔细阅读IntrospectedTableMyBatis3Impl和IntrospectedTableMyBatis3SimpleImpl,这两个类用得多一些。

在MBG中,提供了几种默认的IntrospectedTable的实现,其实在context上设置的runtime对应的就是不同的IntrospectedTable的实现,下面是几种runtime和对应的实现类:

  • 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 数据库驱动版本与数据库版本问题

用高版本的数据库驱动mysql-connector-java 8.0.13连接低版本数据库MySQL 5.7.23,会有以下问题:

  1. 报错
    Cannot obtain primary key information from the database, generated objects may be incomplete
    ...
    
  2. 生成的 mapper 缺少以下接口:
    deleteByPrimaryKey
    selectByPrimaryKey
    updateByPrimaryKeySelective
    updateByPrimaryKey
    

解决

数据库驱动与数据库版本匹配即可,作者在以下两个版本(5.x与8.x)测试通过:

  1. 数据库驱动mysql-connector-java 8.0.13连接数据库MySQL 8.0.11,对应driverClassName: com.mysql.cj.jdbc.Driver
  2. 数据库驱动mysql-connector-java 5.1.29连接数据库MySQL 5.7.23,对应driverClassName: com.mysql.jdbc.Driver

本工程的数据库驱动版本,使用的是当前最新的mysql-connector-java 8.0.13,仅支持连接高版本MySQL 8.x。

如果要在MySQL 5.7.x下运行,只需要修改以下两个地方(注意是5.7.x,其它5.x版本没测试):

  1. 修改pom.xml中mysql-connector.version,改为低版本5.1.39
  2. 本项目的执行,依赖根目录下的generatorConfig.xml文件,将其中driverClass,由com.mysql.cj.jdbc.Driver改为com.mysql.jdbc.Driver

关于作者

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 1. 简介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的...
    笨鸟慢飞阅读 5,422评论 0 4
  • ORA-00001: 违反唯一约束条件 (.) 错误说明:当在唯一索引所对应的列上键入重复值时,会触发此异常。 O...
    我想起个好名字阅读 5,149评论 0 9
  • 1、引言 数据库设计过程中表、字段等的命名规范也算是设计规范的一部分,不过设计规范更多的是为了确保数据库设计的合理...
    SnowflakeCloud阅读 40,938评论 0 48
  • 积攒了一年多的加班,终于在离职档期兑现为一个多月的调休,很多同事都说真好啊,可以利用这一个多月好好去面试呢,其实我...
    寻叶亭阅读 1,234评论 0 3
  • 芮:妈妈我再也不惹你生气了 妈妈:真的吗 芮:是真的 妈妈:再惹我生气怎么办 芮:我真的不会了 对视几秒之后,芮小...
    读读写写萧十一阅读 108评论 0 0