在前面幾篇文章中,筆者介紹了 MyBatis 的運行流程,在此基礎上簡單介紹了手寫 MyBatis 簡易框架與自定義 MyBatis 插件的步驟,相信大家對於 MyBatis 框架的使用流程已經游刃有余了。然而,面對實際開發過程中大量的數據庫表單,傳統的 MyBatis 使用步驟已經顯得繁瑣不堪,本文介紹的就是利用 MyBatis 逆向工程把 MyBatis 框架使用的前期配置准備工作交給代碼生成器完成,從而節省時間提高開發效率。本文涉及到的代碼已上傳至 GitHub: 🔗mybatis-generator-demo 。
話不多說,現在開始🔛🔛🔛!
1. MyBatis逆向工程簡介
所謂 MyBatis 逆向工程,就是 MyBatis 根據數據庫中已經設計好的表單自動生成 domain、mapper、mapper.xml 以及 example 類(用於添加條件),從而大大提高開發效率。在實際開發中,只要敲定了數據庫的表結構就可以通過 MyBatis 逆向工程生成表單對應的基本配置,省去了手動寫 mapper 的工作,然后就可以根據實際業務需求來進行進一步的開發。下面將介紹 MyBatis 的官方生成器插件 MyBatis Generator 以及用戶 itfsw 在 GitHub 開源的一個特別好用的生成器增強插件 mybatis-generator-plugin 。
2. MyBatis逆向工程插件
2.1 MBG插件簡介
MyBatis 提供了官方的代碼生成器 MyBatis Generator(MBG),能夠為所有版本的 MyBatis 以及 2.2.0 之后的 iBatis 版本生成代碼。官方的 MBG 插件能夠生成與數據庫進行簡單交互的 CRUD 操作,在使用時需要在 pom.xml 文件中引入插件的依賴:
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.7</version>
</plugin>
2.2 MBG增強插件簡介
在 MyBatis 的官方 MBG 插件的基礎上,有很多開發者開發了優秀的增強插件並發布在 GitHub 上。本節中介紹的就是用戶 itfsw 開發的 MBG 的增強插件,詳情可見:https://github.com/itfsw/mybatis-generator-plugin 。這是一個 MBG 插件的拓展插件包,方便和減少了代碼開發量。該插件集成了查詢單條數據插件(SelectOneByExamplePlugin)、MySQL分頁插件(LimitPlugin)、數據Model鏈式構建插件(ModelBuilderPlugin)、Example Criteria 增強插件(ExampleEnhancedPlugin)、Example 目標包修改插件(ExampleTargetPlugin)、批量插入插件(BatchInsertPlugin)、邏輯刪除插件(LogicalDeletePlugin)、數據Model屬性對應Column獲取插件(ModelColumnPlugin)、存在即更新(UpsertPlugin)等等插件。在實際項目中使用時需要引入插件的依賴:
<dependency>
<groupId>com.itfsw</groupId>
<artifactId>mybatis-generator-plugin</artifactId>
<version>1.3.2</version>
</dependency>
3. MyBatis逆向工程實踐
在介紹了兩款與 MyBatis 逆向工程相關的插件之后,下面將通過一個實際項目來實踐 MyBatis 的逆向工程。
3.1 前期准備
3.1.1 構建SpringBoot項目並集成MyBatis
本文中采用 SpringBoot + MyBatis 來構建項目,這種構建方式也是目前實際開發中常用的方式。項目構建完成后新建對應的 package 用於存放生成器生成的代碼,如下圖所示。
在上圖中,domain
文件夾用於存放根據數據庫表單生成的 POJO 類,mapper
文件夾用於存放生成器生成的表單對應的接口,而在文件夾 resoucres/mapper
下存放的是生成的 mapper 接口對應的 xml 配置文件。
3.1.2 配置pom.xml文件
進一步需要在 pom.xml 文件中配置項目相關的 MBG 依賴、MySQL 依賴、Lombok 依賴等等,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.chiaki</groupId>
<artifactId>mybatis-generator-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>mybatis-generator-demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--lombok插件-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.42</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<!--MBG插件-->
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.7</version>
<configuration>
<!-- 是否覆蓋,true表示會替換生成的Java文件,false則不覆蓋 -->
<overwrite>true</overwrite>
<verbose>true</verbose>
</configuration>
<dependencies>
<!--mysql驅動包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.42</version>
</dependency>
<!-- MBG擴展包 -->
<dependency>
<groupId>com.itfsw</groupId>
<artifactId>mybatis-generator-plugin</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
3.1.3 配置application.yml文件
接下來需要配置 SpringBoot 項目的 application.yml 配置文件,如下所示:
# spring配置
spring:
# 數據庫配置
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatis_generator_demo?useUnicode=true&characterEncoding=utf-8
username: root
password: admin
# mybatis配置
mybatis:
# 指定xml文件的位置
mapper-locations: classpath:mapper/*.xml
# 指定domain文件的位置
type-aliases-package: com.chiaki.domain
# 添加日志實現類以打印日志
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 服務器配置
server:
# 指定端口
port: 8079
在 SpringBoot 集成 MyBatis 的項目中,只需要將 MyBatis 的相關配置寫道 SpringBoot 的配置文件中即可。如上圖所示,配置相應的 MySQL 數據源以及相應的 MyBatis 設置以及指定訪問端口。
3.1.4 准備數據庫表單
准備逆向工程需要的表單,這里准備 student_info 以及 class_info 兩張表,如下所示:
CREATE DATABASE /*!32312 IF NOT EXISTS*/`mybatis_generator_demo` /*!40100 DEFAULT CHARACTER SET utf8 */;
/*Table structure for table `class_info` */
DROP TABLE IF EXISTS `class_info`;
CREATE TABLE `class_info` (
`class_id` int(10) NOT NULL COMMENT '班級ID',
`class_name` varchar(20) DEFAULT NULL COMMENT '班級名稱',
PRIMARY KEY (`class_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*Data for the table `class_info` */
insert into `class_info`(`class_id`,`class_name`) values
(202101,'A班'),
(202102,'B班'),
(202103,'C班');
/*Table structure for table `student_info` */
DROP TABLE IF EXISTS `student_info`;
CREATE TABLE `student_info` (
`id` int(10) NOT NULL AUTO_INCREMENT COMMENT '學生ID',
`name` varchar(20) DEFAULT NULL COMMENT '姓名',
`sex` varchar(20) DEFAULT NULL COMMENT '性別',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
/*Data for the table `student_info` */
insert into `student_info`(`id`,`name`,`sex`) values
(1,'張三','男'),
(2,'托尼·李四','男'),
(3,'王五','女'),
(4,'趙六','男');
3.2 編寫MBG配置文件
3.2.1 配置generatorConfig.xml文件
做好以上配置之后就來到最為關鍵的一步,即編寫逆向工程需要的 generatorConfig.xml 生成器配置文件,如下所示。在實際開發中可以借鑒官網的 MyBatis Generator 配置文件以及自己的業務需求自行編寫。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="Tables" targetRuntime="MyBatis3">
<!-- 批量插入插件 -->
<plugin type="com.itfsw.mybatis.generator.plugins.BatchInsertPlugin">
<property name="allowMultiQueries" value="false"/>
</plugin>
<!--重命名查詢class名稱-->
<plugin type="org.mybatis.generator.plugins.RenameExampleClassPlugin" >
<property name="searchString" value="Example$"/>
<property name="replaceString" value="Criteria"/>
</plugin>
<!-- 查詢單條數據插件 -->
<plugin type="com.itfsw.mybatis.generator.plugins.SelectOneByExamplePlugin"/>
<!-- MySQL分頁插件 -->
<plugin type="com.itfsw.mybatis.generator.plugins.LimitPlugin">
<!-- 通過配置startPage影響Example中的page方法開始分頁的頁碼,默認分頁從0開始 -->
<property name="startPage" value="1"/>
</plugin>
<!-- 自定義注釋插件 -->
<plugin type="com.itfsw.mybatis.generator.plugins.CommentPlugin">
<!-- 自定義模板路徑 -->
<property name="template" value="src/main/resources/mybatis-generator-comment.ftl" />
</plugin>
<!-- Lombok插件 -->
<plugin type="com.itfsw.mybatis.generator.plugins.LombokPlugin">
<!-- @Builder 必須在 Lombok 版本 >= 1.18.2 的情況下 -->
<property name="@Builder" value="false"/>
<!-- @NoArgsConstructor 和 @AllArgsConstructor 使用規則和Lombok一致 -->
<property name="@AllArgsConstructor" value="false"/>
<property name="@NoArgsConstructor" value="false"/>
</plugin>
<!-- xml重新生成時覆蓋 -->
<plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin"/>
<!-- 注釋 -->
<commentGenerator>
<property name="javaFileEncoding" value="UTF-8"/>
</commentGenerator>
<!-- JDBC連接 -->
<jdbcConnection
driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis_generator_demo?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8"
userId="root"
password="admin">
<!-- 針對mysql數據庫 -->
<property name="useInformationSchema" value="true"/>
</jdbcConnection>
<!-- 非必需,類型處理器,在數據庫類型和java類型之間的轉換控制-->
<!-- 默認false,把JDBC DECIMAL 和 NUMERIC 類型解析為 Integer,為 true時把JDBC DECIMAL 和
NUMERIC 類型解析為java.math.BigDecimal -->
<javaTypeResolver>
<!-- 是否使用bigDecimal, false可自動轉化以下類型(Long, Integer, Short, etc.) -->
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- domain領域模型 其中targetPackage需要根據你自己創建的目錄進行改動 -->
<javaModelGenerator targetPackage="com.chiaki.mybatisgeneratordemo.domain" targetProject="src/main/java">
<!-- 從數據庫返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
<!-- enableSubPackages:是否讓schema作為包的后綴 -->
<property name="enableSubPackages" value="true" />
</javaModelGenerator>
<!-- mapper xml文件 -->
<sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources">
<!-- enableSubPackages:是否讓schema作為包的后綴 -->
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<!-- Mapper接口 -->
<javaClientGenerator targetPackage="com.chiaki.mybatisgeneratordemo.mapper" targetProject="src/main/java" type="XMLMAPPER">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!-- 配置表信息 -->
<!-- tableName為對應的數據庫表 -->
<table tableName="student_info">
<property name="useActualColumnNames" value="false"/>
<generatedKey column="id" sqlStatement="Mysql" identity="true" />
</table>
<table tableName="class_info">
<property name="useActualColumnNames" value="false"/>
<generatedKey column="id" sqlStatement="Mysql" identity="true" />
</table>
</context>
</generatorConfiguration>
3.2.2 配置mybatis-generator-comment.ftl文件
在上述配置文件中,我們使用了 itfsw 的 MBG 增強插件,其中包括自定義的注釋插件,其配置如下所示。具體的配置細節可參考 itfsw 的 Github 對應的項目。
<?xml version="1.0" encoding="UTF-8"?>
<template>
<!-- 調用此方法可將文件級注釋添加到生成的Java文件中 -->
<comment ID="addJavaFileComment"></comment>
<comment ID="addComment"></comment>
<comment ID="addRootComment"></comment>
<!-- 將數據庫表字段的注釋添加到相應實體的變量上 -->
<comment ID="addFieldComment">
<![CDATA[
<#if introspectedColumn??>
<#if introspectedColumn.remarks?? && introspectedColumn.remarks != ''>
<#list introspectedColumn.remarks ? split("\n") as remark>
/** ${remark} **/
</#list>
</#if>
</#if>
]]>
</comment>
<!-- 為模型類添加注釋 -->
<comment ID="addModelClassComment">
<![CDATA[
<#if introspectedTable.remarks?? && introspectedTable.remarks != ''>
<#list introspectedTable.remarks?split("\n") as remark>
/**
* ${remark}
**/
</#list>
</#if>
]]>
</comment>
<!-- 為內部類添加注釋 -->
<comment ID="addClassComment">
<![CDATA[
/**
* ${introspectedTable.fullyQualifiedTable}
**/
]]>
</comment>
<comment ID="addEnumComment"></comment>
<comment ID="addInterfaceComment"></comment>
<comment ID="addGetterComment"></comment>
<comment ID="addSetterComment"></comment>
<comment ID="addGeneralMethodComment"></comment>
</template>
3.3 運行MBG生成器生成代碼
在設置好上述的配置文件之后,就可以執行 maven 命令開始生成代碼了,這里可以通過 maven 命令生成:
mvn mybatis-generator:generate
也可以找到 maven 插件雙擊生成:
運行之后可以在目錄中看到已經生成的代碼文件,如下所示:
3.4 生成代碼測試
生成代碼后編寫相應的測試類 testQuery 對生成的代碼進行測試,如下所示:
@RunWith(SpringRunner.class)
@SpringBootTest()
public class testQuery {
// mapper注入
@Resource
StudentInfoMapper studentInfoMapper;
@Resource
ClassInfoMapper classInfoMapper;
@Test
public void testQueryStudentInfo() {
// 測試根據主鍵查找學生信息
StudentInfo studentInfo = studentInfoMapper.selectByPrimaryKey(2);
System.out.println(studentInfo);
}
@Test
public void testQueryStudentInfoByConditions() {
// 增強查詢
StudentInfoCriteria studentInfoCriteria = new StudentInfoCriteria();
// 條件組合
studentInfoCriteria.createCriteria()
// id字段在{1, 3, 4}當中
.andIdIn(Arrays.asList(1, 3, 4))
// sex = "男"
.andSexEqualTo("男");
// 得到查詢結果列表
List<StudentInfo> studentInfos = studentInfoMapper.selectByExample(studentInfoCriteria);
System.out.println(studentInfos);
ClassInfoCriteria classInfoCriteria = new ClassInfoCriteria();
// 查詢條件:class_id = 202101
classInfoCriteria.createCriteria().andClassIdEqualTo(202101);
// 得到查詢結果
List<ClassInfo> classInfos = classInfoMapper.selectByExample(classInfoCriteria);
System.out.println(classInfos);
}
}
如上所示編寫了查詢 student_info 與 class_info 表的測試方法,可以看出 MyBatis 逆向工程生成的代碼可以包含了基本查詢方法,同時也支持組合條件進行查詢。在運行測試方法前,還需要再 SpringBoot 項目的啟動類上加入 @MapperScan("com.chiaki.mybatisgeneratordemo.mapper")
來掃描 mapper 接口。然后運行測試方法得到如下結果:
從運行結果來看,逆向工程生成的代碼能夠經得起檢驗,測試結果也完全正確。
總結
本文首先介紹了 MyBatis 逆向工程的概念,然后介紹了與逆向工程相關的 MBG 插件與增強插件,最后通過一個 SpringBoot 集成 MyBatis 的項目進行了逆向工程的實踐並取得了正確的效果。在當今的互聯網開發中,時間就是效率,如果只會簡單的 CRUD 操作恐怕已經無法滿足企業對后端開發工程師的要求,因此需要掌握這種自動生成代碼的技巧,同時加油不斷提升自己!
參考資料
MBG 官方社區:http://mybatis.org/generator/
iffsw 增強插件項目:https://github.com/itfsw/mybatis-generator-plugin
淺析MyBatis(一):由一個快速案例剖析MyBatis的整體架構與運行流程
淺析MyBatis(二):手寫一個自己的MyBatis簡單框架
淺析MyBatis(三):聊一聊MyBatis的實用插件與自定義插件
🔚🔚🔚
覺得有用的話就點個推薦吧~