Mybatis詳解系列(五)--Mybatis Generator和全註解風格的MyBatis3DynamicSql
阿新 • • 發佈:2020-05-03
# 簡介
Mybatis Generator (MBG) 是 Mybatis 官方提供的程式碼生成器,通過它可以在專案中自動生成簡單的 CRUD 方法,甚至**“無所不能”**的高階條件查詢(**MyBatis3DynamicSql** ),讓我們避免了進行資料庫互動時需要手動建立物件和配置 Mybatis 對映等基礎工作。
另外,MBG 有很好地擴充套件性,它提供了大量的介面和外掛用來給我們自定義生成的程式碼應該是什麼樣子,例如我們可以自定義註釋、程式碼格式化、新增 toString 方法等。本文將講解如何使用這些介面。
本文內容大致如下,由於篇幅較長,可選擇閱讀:
1. 如何使用 MBG 生成程式碼;
2. 詳解 MBG 的配置,將配置使用自定義註釋生成器、實體類中新增 toString/equals/hashCode方法等。
3. MyBatis3DynamicSql 風格(無 XML) API 的使用。
通過本文的學習,你將能夠通過簡單改造 MBG 來生成自己想要的程式碼,另外,我們也將認識強大的 MyBatis3DynamicSql 風格(它提供的條件類使用 Lambda 解耦,全註解,支援單表查詢、多表查詢、分頁、排序、分組等等)。
# 關於 MBG 生成程式碼的風格
MBG 支援生成**不同風格**、不同語言的程式碼,例如,MBG 能夠生成 Java 或 Kotlin 程式碼。另外,MBG 支援生成舊版的 MyBatis3 風格(**我們常用的 xml 配置屬於 MyBatis3 風格,官方認為這種風格已經過時**),也支援新版的 MyBatis3DynamicSql 的風格(**MyBatis3DynamicSql 風格為官方推薦**)。幾種風格的對比如下:
| 程式碼風格 | 描述 |
| ------------------ | ------------------------------------------------------------ |
| MyBatis3DynamicSql | 預設風格,官方推薦
Java程式碼
全註解,不生成 XML 檔案
生成的高階條件查詢靈活性較大,使用 lambda 表示式避免條件物件滲透到上一層
一個表生成一個實體類
| | MyBatis3Kotlin | Kotlin 程式碼,本文不涉及 | | MyBatis3 | 早期風格
Java程式碼
能夠生成 MyBatis3 相容的 xml 或 全註解
生成的高階條件查詢靈活性較小,條件類滲透到上一層,而且 sql 和程式碼耦合度較高
一個表除了生成基本類,可能還會生成主鍵類和BLOB類(如果指定的話)
| | MyBatis3Simple | MyBatis3 的簡易版
Java程式碼
能夠生成 MyBatis3 相容的 xml 或 全註解
不生成 "by example" 或 "selective" 的方法
一個表生成一個實體類
| 由於 MyBatis3 風格生成的 Example 類存在的問題,**實際專案中建議使用 MyBatis3Simple 風格或官方推薦的 MyBatis3DynamicSql 風格**。 # 關於 MBG 檔案覆蓋的問題 當我們在迭代開發環境中使用 MBG,需要注意檔案覆蓋的問題,預設情況下,檔案覆蓋規則如下: 1. 如果 XML 已經存在,MBG 會採用檔案合併的方式。 它不會修改你自定義的節點,但是會更新原來生成的 CRUD 節點(如果表發生變化)。**檔案合併有個前提,就是原來生成的 CRUD 節點必須包含 @mbg.generated 的預設註釋**。否則,當再次執行 MBG 時,它將無法識別哪些是它生成過的節點,於是會出現下圖的情況,即 CRUD 節點被重複插入。 ![https://img2020.cnblogs.com/blog/1731892/202005/1731892-20200502235440091-1666766703.png) 2. 如果 Java 或 Kotlin 檔案已經存在,MBG 可以覆蓋現有檔案或使用其他唯一名稱儲存新生成的檔案,這取決於你如何配置`false `。
那麼,下面開始詳細介紹如何使用 MBG。
# 專案環境的說明
## 工程環境
JDK:1.8.0_231(要求 JDK8 及以上)
maven:3.6.1
IDE:Spring Tool Suites4 for Eclipse 4.12
mysql:5.7.28
## 資料庫指令碼
具體的 sql 指令碼也提供好了([指令碼路徑]( https://github.com/ZhangZiSheng001/mybatis-projects/sql))。
# maven配置
## pom.xml配置
MBG 支援使用**Java 程式碼、maven 外掛、Eclipse 外掛等**方式執行,本文使用 maven 外掛方式,所以需要在 build/plugins 節點引入 MBG 外掛,並加入其它依賴項,例如 mybatis、mysql 驅動等。另外,因為本文也需要用到 Java 程式來執行 MBG(當使用自定義類時),所以把外掛的依賴項從 build/plugins/plugin 節點中單獨取出來。
```xml
org.mybatis.generator
mybatis-generator-core
1.4.0
org.mybatis
mybatis
3.5.4
org.mybatis.dynamic-sql
mybatis-dynamic-sql
1.1.4
mysql
mysql-connector-java
8.0.15
ch.qos.logback
logback-core
1.2.3
jar
ch.qos.logback
logback-classic
1.2.3
jar
org.mybatis.generator
mybatis-generator-maven-plugin
1.4.0
Generate MyBatis Artifacts
package
generate
true
default
false
${basedir}/src/main/resources/generatorConfig.xml
true
```
## 外掛引數詳解
plugin/configuration 節點可以配置影響 MBG 行為的引數,如下:
| 引數 | 表示式 | 型別 | 描述 |
| --------------------------------------------------- | ----------------------------------------------- | ---------------- | ------------------------------------------------------------ |
| configurationFile | ${mybatis.generator.configurationFile} | java.io.File | 配置檔案路徑。
預設為${basedir}/src/main/resources/generatorConfig.xml | | contexts | ${mybatis.generator.contexts} | java.lang.String | 指定使用配置檔案中的哪個context
多個用逗號隔開 | | jdbcDriver | ${mybatis.generator.jdbcDriver} | java.lang.String | JDBC 驅動 | | jdbcPassword | ${mybatis.generator.jdbcPassword} | java.lang.String | JDBC 密碼 | | jdbcURL | ${mybatis.generator.jdbcURL} | java.lang.String | JDBC URL | | jdbcUserId | ${mybatis.generator.jdbcUserId} | java.lang.String | JDBC 使用者名稱 | | outputDirectory | ${mybatis.generator.outputDirectory} | java.io.File | MBG 檔案輸出路徑。只有在配置檔案中配置targetProject="MAVEN"(區分大小寫),才會使用這個路徑。
預設為${project.build.directory}/generated-sources/mybatis-generator | | overwrite | ${mybatis.generator.overwrite} | boolean | 是否覆蓋已經存在的同名Java檔案。
如果為true,Java檔案將被覆蓋。 如果為false,MBG會將新生成唯一名稱的Java檔案(例如MyClass.java.1,MyClass.java.2)
預設為false | | sqlScript | ${mybatis.generator.sqlScript} | java.lang.String | 生成程式碼之前需要執行的SQL指令碼路徑。
如果指定,則必須提供jdbcDriver,jdbcURL、jdbcUserId、jdbcPassword。 | | tableNames | ${mybatis.generator.tableNames} | java.lang.String | 需要生成程式碼的表
多個用逗號隔開 | | verbose | ${mybatis.generator.verbose} | boolean | 是否列印日誌
預設為false | | includeCompileDependencies | ${mybatis.generator.includeCompileDependencies} | boolean | 如果為true,則作用域為“ compile”,“ provided”和“ system”的依賴將新增到生成器的類路徑中。
預設為false | | includeAllDependencies | ${mybatis.generator.includeAllDependencies} | boolean | 如果為true,則所有作用域的依賴將新增到生成器的類路徑中。
預設為false | | skip | ${mybatis.generator.skip} | boolean | 專案啟動時跳過 MBG。
預設false | # 程式碼生成規則配置 使用 maven 外掛的方式不需要編寫程式碼,只要將規則配置到 generatorConfig.xml 檔案就行,配置內容主要為: 1. 如何連線到資料庫 2. 生成什麼物件,以及如何生成它們 3. 哪些表將用於物件生成 下面先給一個簡單版的,後面再具體講解這些引數的意義: ```xml
```
# 命令執行
## maven 外掛的執行方式
maven build,輸入`mybatis-generator:generate`,生成成功。
## Java程式的執行方式
通常情況下,我們都是使用 maven 外掛的方式,但是,當我們在 MBG 中指定了自定義的實現,使用 maven 外掛可能會報錯,這個時候就需要通過 Java 程式的方式執行 MBG,具體方法如下:
```java
public static void main(String[] args) throws Exception {
// LogFactory.forceSlf4jLogging();
// System.setProperty("user.name", "zzs");
// 這個集合記錄著生成、合併、覆蓋檔案的資訊
List warnings = new ArrayList();
InputStream in = MybatisGenerator.class.getClassLoader().getResourceAsStream("generatorConfig.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(in);
// 不覆蓋 Java 檔案
boolean overwrite = false;
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
// 生成檔案
myBatisGenerator.generate(null);
// 列印資訊
warnings.forEach(System.err::println);
}
```
# 生成規則詳解
generatorConfig.xml 的頂層結構如下:
- generatorConfiguration(配置)
- classPathEntry(JDBC驅動路徑)
- properties(properties檔案路徑)
- context(生成物件的環境)
- property(Context作用域引數)
- jdbcConnection(JDBC連線)
- connectionFactory(JDBC連線工廠)
- commentGenerator(註釋生成器)
- javaModelGenerator(實體物件生成器)
- javaClientGenerator(Mapper 介面或實現類生成器)
- sqlMapGenerator(xml 生成器)
- table(用於生成物件的表)
- javaTypeResolver(Java 型別處理器)
- plugin(外掛)
下面選擇部分節點展開分析:
## context*
` `節點用於指定生成一系列物件的環境。我們可以在配置檔案中配置多個` `節點來實現從**不同資料來源**或採用不同生成引數生成物件。
### 屬性
這裡最重要的屬性是**targetRuntime**,它直接決定該環境下生成的程式碼風格,常用的風格為 MyBatis3DynamicSql 和 MyBatis3Simple。
| 屬性 | 描述 |
| ---------------------- | ------------------------------------------------------------ |
| id | 用於唯一標識指定環境。必選屬性 |
| defaultModelType | 指定實體物件的型別。包括三種:
**flat**:一個表生成一個實體類;
**conditional**:和 hierarchical 差不多,區別在於如果表只有一個主鍵,不會單獨去生成一個主鍵類;
**hierarchical**:除了生成基本類,如果表中包含主鍵或 BLOB 列,都會單獨再生成一個主鍵類或BLOB類
**預設為 conditional**,如果 targetRuntime 為 "MyBatis3Simple"、"MyBatis3DynamicSql"或"MyBatis3Kotlin",則該屬性忽略 | | **targetRuntime** | 用於指定生成程式碼的風格。預設為 MyBatis3DynamicSql | | introspectedColumnImpl | 指定`org.mybatis.generator.api.IntrospectedColumn`實現類。該類可以看成是某一列的所有資訊 | ### 子節點 ` `包含以下子節點:
- `` (0..N)
- `` (0..N)
- `` (0 or 1)
- `/` (1 Required)
- `` (0 or 1)
- `` (1 Required)
- `` (0 or 1)
- `` (0 or 1)
- `` (1..N)
其中,`
Java程式碼
全註解,不生成 XML 檔案
生成的高階條件查詢靈活性較大,使用 lambda 表示式避免條件物件滲透到上一層
一個表生成一個實體類
| | MyBatis3Kotlin | Kotlin 程式碼,本文不涉及 | | MyBatis3 | 早期風格
Java程式碼
能夠生成 MyBatis3 相容的 xml 或 全註解
生成的高階條件查詢靈活性較小,條件類滲透到上一層,而且 sql 和程式碼耦合度較高
一個表除了生成基本類,可能還會生成主鍵類和BLOB類(如果指定的話)
| | MyBatis3Simple | MyBatis3 的簡易版
能夠生成 MyBatis3 相容的 xml 或 全註解
不生成 "by example" 或 "selective" 的方法
一個表生成一個實體類
| 由於 MyBatis3 風格生成的 Example 類存在的問題,**實際專案中建議使用 MyBatis3Simple 風格或官方推薦的 MyBatis3DynamicSql 風格**。 # 關於 MBG 檔案覆蓋的問題 當我們在迭代開發環境中使用 MBG,需要注意檔案覆蓋的問題,預設情況下,檔案覆蓋規則如下: 1. 如果 XML 已經存在,MBG 會採用檔案合併的方式。 它不會修改你自定義的節點,但是會更新原來生成的 CRUD 節點(如果表發生變化)。**檔案合併有個前提,就是原來生成的 CRUD 節點必須包含 @mbg.generated 的預設註釋**。否則,當再次執行 MBG 時,它將無法識別哪些是它生成過的節點,於是會出現下圖的情況,即 CRUD 節點被重複插入。 ![https://img2020.cnblogs.com/blog/1731892/202005/1731892-20200502235440091-1666766703.png) 2. 如果 Java 或 Kotlin 檔案已經存在,MBG 可以覆蓋現有檔案或使用其他唯一名稱儲存新生成的檔案,這取決於你如何配置`
預設為${basedir}/src/main/resources/generatorConfig.xml | | contexts | ${mybatis.generator.contexts} | java.lang.String | 指定使用配置檔案中的哪個context
多個用逗號隔開 | | jdbcDriver | ${mybatis.generator.jdbcDriver} | java.lang.String | JDBC 驅動 | | jdbcPassword | ${mybatis.generator.jdbcPassword} | java.lang.String | JDBC 密碼 | | jdbcURL | ${mybatis.generator.jdbcURL} | java.lang.String | JDBC URL | | jdbcUserId | ${mybatis.generator.jdbcUserId} | java.lang.String | JDBC 使用者名稱 | | outputDirectory | ${mybatis.generator.outputDirectory} | java.io.File | MBG 檔案輸出路徑。只有在配置檔案中配置targetProject="MAVEN"(區分大小寫),才會使用這個路徑。
預設為${project.build.directory}/generated-sources/mybatis-generator | | overwrite | ${mybatis.generator.overwrite} | boolean | 是否覆蓋已經存在的同名Java檔案。
如果為true,Java檔案將被覆蓋。 如果為false,MBG會將新生成唯一名稱的Java檔案(例如MyClass.java.1,MyClass.java.2)
預設為false | | sqlScript | ${mybatis.generator.sqlScript} | java.lang.String | 生成程式碼之前需要執行的SQL指令碼路徑。
如果指定,則必須提供jdbcDriver,jdbcURL、jdbcUserId、jdbcPassword。 | | tableNames | ${mybatis.generator.tableNames} | java.lang.String | 需要生成程式碼的表
多個用逗號隔開 | | verbose | ${mybatis.generator.verbose} | boolean | 是否列印日誌
預設為false | | includeCompileDependencies | ${mybatis.generator.includeCompileDependencies} | boolean | 如果為true,則作用域為“ compile”,“ provided”和“ system”的依賴將新增到生成器的類路徑中。
預設為false | | includeAllDependencies | ${mybatis.generator.includeAllDependencies} | boolean | 如果為true,則所有作用域的依賴將新增到生成器的類路徑中。
預設為false | | skip | ${mybatis.generator.skip} | boolean | 專案啟動時跳過 MBG。
預設false | # 程式碼生成規則配置 使用 maven 外掛的方式不需要編寫程式碼,只要將規則配置到 generatorConfig.xml 檔案就行,配置內容主要為: 1. 如何連線到資料庫 2. 生成什麼物件,以及如何生成它們 3. 哪些表將用於物件生成 下面先給一個簡單版的,後面再具體講解這些引數的意義: ```xml
**flat**:一個表生成一個實體類;
**conditional**:和 hierarchical 差不多,區別在於如果表只有一個主鍵,不會單獨去生成一個主鍵類;
**hierarchical**:除了生成基本類,如果表中包含主鍵或 BLOB 列,都會單獨再生成一個主鍵類或BLOB類
**預設為 conditional**,如果 targetRuntime 為 "MyBatis3Simple"、"MyBatis3DynamicSql"或"MyBatis3Kotlin",則該屬性忽略 | | **targetRuntime** | 用於指定生成程式碼的風格。預設為 MyBatis3DynamicSql | | introspectedColumnImpl | 指定`org.mybatis.generator.api.IntrospectedColumn`實現類。該類可以看成是某一列的所有資訊 | ### 子節點 `
`new Employee().withAddress("北京").withDeleted(false).withName("zzs001");` | | **org.mybatis.generator.plugins.MapperAnnotationPlugin** | 用於在 Mapper 介面中新增`@Mapper`介面 | | org.mybatis.generator.plugins.MapperConfigPlugin | 用於生成 Mybatis 的主配置檔案 MapperConfig | | org.mybatis.generator.plugins.RenameExampleClassPlugin | 用於重新命名 Example 類 | | org.mybatis.generator.plugins.RowBoundsPlugin | 用於在 Mapper 介面的 selectByExample 方法引數中加入 RowBounds 引數,用於支援分頁 | | org.mybatis.generator.plugins.VirtualPrimaryKeyPlugin | 用於指定表的主鍵 | 外掛的配置方式非常簡單,如下: ```xml