如题
https://github.com/uncleAndyChen/mybatis-generator
如果表名采用驼峰式命名(不推荐驼峰式命名,推荐下划线命名),运行本工程生成表配置内容,要求 MySQL 的配置项:lower_case_table_names
为0或者2的情况下创建的数据表,否则,生成的表配置内容的表名,全是小写的,并非驼峰式命名法。表配置内容生成好之后,重新生成 mapper 时,数据库配置项:lower_case_table_names
的值,对生成结果没有影响。
有关 MySQL 命名规范,请参考:有关 MySQL 命名规范,用驼峰命名法与下划线命名法的取舍,请关注这篇文章提到的 mapUnderscoreToCamelCase 配置项。
本文对应的完整项目
- github: https://github.com/uncleAndyChen/mybatis-generator
- gitee: https://gitee.com/uncleAndyChen/mybatis-generator
进入以上项目路径可查看更详细的介绍。
关于该项目
本项目最初想要解决数据库表名、字段名的命名法与 java 的类、属性命名法不一致带来的一系列问题。
当然,本项目的 MBG 扩展类还做了一些其他事情,比如方便分表时做表名替换,更详细的,请参考: MBG 扩展类 module
曾尝试将数据库表名、字段名也采用驼峰命名法。
现在已经改成:
- 数据库表名、字段名保持下划线命名法。
- 针对自定义 SQL 查询结果,对应的自定义 POJO 保持驼峰命名法,查询数据库的 SQL 语句保留原生下划线,并且不用写 resultMap。
- 做到了 Java 规范与 MySQL 命名规范不一致的完美兼顾。
已添加查询示例,不过仅仅是查询示例,没有考虑到项目架构的合理性。实际项目不会在 web 层直接调用 dal 层,实际项目会有业务层和接口层。
本扩展的作用
- 生成的*Mapper.xml文件中的脚本,表名取MBG所需配置文件中配置的值(工程中的配置文件是:generatorConfig.xml),而不是从数据库读取到的值。
- 如果数据库表名采用下划线命名法,请忽略这个作用。
- 数据库表名、字段名命名法:
- 之前本人推荐采用驼峰命名法。
- 想要保持统一的命名规则。
- 不知道通过配置的方式兼顾两种命名法,即数据库表名、字段名在采用下划线命名法的情况下,通过 MBG 生成的对应每一个表的 POJO 采用驼峰命名法,查询数据时不需要考虑 MBG 生成的 xml 映射文件中的
resultMap
,如 parent_id 与 parentId 的映射。
- 现在推荐下划线命名法。
- 这是为了避免因 windows 与 linux 以及云数据库的大小写敏感不一致,从而带来不必要的麻烦。
- 同时也是考虑到绝大多数同行的习惯。
- 最主要的,是解决了之前不知道的兼顾两种命名法的办法(好象有一点拗口~~)
- 之前本人推荐采用驼峰命名法。
- 给表名添加MySQL“边界”,用 `(左上角数字键1左边、Tab键上边、Esc键下边的键)引起来。目的是分表时进行表名替换,把每张个表的表名当作一个整体,避免表名补充部分替换。
解决两个问题
- 适应lower_case_table_names的三种配置值。
- 利用MyBatis插件,根据业务规则,对表名进行动态替换。
注:项目根目录下有更详细的介绍,点击以下链接查看:
- github: https://github.com/uncleAndyChen/mybatis-generator
- gitee: https://gitee.com/uncleAndyChen/mybatis-generator
自己扩展的好处
- 比起直接修改MBG源代码,这种方式对MBG无代码侵入,方便将来升级MBG。
- 符合面向对象设计的【开闭原则】,即通过增加代码来为软件添加新功能,而不是直接修改原有代码。这一点,MBG做得非常好,除了可以非常方便的扩展之外,还可以写各种插件以实现自己的业务需要。
使用自己的扩展类
在配置文件generatorConfig.xml的context节点,配置runtime值,指向自己的扩展类,需要带包名,如本例:1
<context id="Mysql" targetRuntime="mybatis.generator.enhance.IntrospectedTableEnhanceImpl" defaultModelType="flat">
扩展类的代码很简单,只有十几行1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18import org.mybatis.generator.codegen.mybatis3.IntrospectedTableMyBatis3Impl;
public class IntrospectedTableEnhanceImpl extends IntrospectedTableMyBatis3Impl {
public String getFullyQualifiedTableNameAtRuntime() {
return getTableNameFromConfigFile();
}
public String getAliasedFullyQualifiedTableNameAtRuntime() {
return getTableNameFromConfigFile();
}
private String getTableNameFromConfigFile() {
String tableName = this.getTableConfiguration().getTableName();
return "`" + tableName + "`";
}
}
两种运行方式
以程序方式运行
仿照官方的org.mybatis.generator.api.ShellRunner
,写一段代码,以程序的方式运行。本工程的代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40public 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运行需要的配置文件路径配置对。1
configFile=C:/workspace/mybatis-generator/generatorConfig.xml
cmd窗口运行jar文件
- 下MBG的jar包,传送门,解压,找到
mybatis-generator-1.3.7.jar
备用。 - 将本模块生成jar文件,生成的jar文件名
mybatis-generator-enhance.jar
。 - 将两个jar文件以及配置文件放到model与dal项目所在的目录下,在 cmd 窗口执行:
1
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
2Cannot obtain primary key information from the database, generated objects may be incomplete
...生成的 mapper 缺少以下接口:
1
2
3
4deleteByPrimaryKey
selectByPrimaryKey
updateByPrimaryKeySelective
updateByPrimaryKey
解决
数据库驱动与数据库版本匹配即可,作者在以下两个版本(5.x与8.x)测试通过:
- 数据库驱动
mysql-connector-java 8.0.13
连接数据库MySQL 8.0.11
,对应driverClassName: com.mysql.cj.jdbc.Driver
- 数据库驱动
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版本没测试):
- 修改pom.xml中
mysql-connector.version
,改为低版本5.1.39
。 - 本项目的执行,依赖根目录下的
generatorConfig.xml
文件,将其中driverClass
,由com.mysql.cj.jdbc.Driver
改为com.mysql.jdbc.Driver
。