MyBatisリバースエンジニアリング完全ガイド
このドキュメントでは、MyBatis Generator(MBG)の公式ツールとMyBatis-Plusコードジェネレータを含む、MyBatisリバースエンジニアリング(コードジェネレータ)に関するすべての知識を、構成から実際の作業まで網羅的に網羅しています。
リバースエンジニアリング概要
リバースエンジニアリングとは?
MyBatisリバースエンジニアリングReverse Engineeringとは、データベース表構造を介して、Javaエンティティークラス、Mapperインタフェース、 Mapper XMLマッピングファイル を自動的に生成するプロセスである。
数据库表结构 ──→ 逆向工程工具 ──→ Java 实体类
(Generator) Mapper 接口
Mapper XML
Example 类
Service(MP)
Controller(MP)
なぜリバースエンジニアリングが必要か
| 従来手书き方式 | リバースエンジニング方式 |
|---|---|
| エンティティークラスの手動作成、フィールド単位のマッピング | 自動生成、ワンクリックで完了 |
| 手書きCRUDのSQL 文 | 単一テーブルCRUDの自動生成 |
| スペルミス、フィールドの欠落が容易 | データベースとの完全な整合性 |
| 新規フィールドは手動で複数の変更が必要 | 再生可能です。 |
| 時間と退屈。 | 秒で完了。 |
主なリバースエンジニアリングツールの比較
| 工具 | フルネーム | メンテナ | 特長 |
|---|---|---|---|
| MyBatis Generator(MBG) | MyBatis Generator | MyBatis公式ページ | 公式ツール、安定した信頼性、生成エンティティ+Mapper+XML+Example |
| MyBatis-Plus Generator | MP CodeGenerator | MyBatis-Plus コミュニティ | より強力な機能、エンティティー +Mapper+XML+Service+Controller、テンプレートのサポート |
| IDEAプラグインFree MyBatis Tool | EasyCode、MyBatisCode Helper | サードパーティ·パーティ | 迅速な開発に適した視覚的操作 |
| RuoYiコードジェネレータ | コードで作成する | Ruoyi コミュニティ | 完全なバックエンドコードを生成するテンプレートエンジン。 |
リバースエンジニアリングは何を生み出す?
MyBatis Generatorの生成物
src/main/java/
└── com/example/entity/
├── User.java ← 实体类(POJO)
└── UserExample.java ← 查询条件类(QBC风格)
└── com/example/mapper/
└── UserMapper.java ← Mapper 接口
src/main/resources/
└── mapper/
└── UserMapper.xml ← SQL 映射文件MyBatis-Plus Generator 生成物
src/main/java/
└── com/example/
├── entity/User.java ← 实体类(含 Lombok / Swagger 注解)
├── mapper/UserMapper.java ← Mapper 接口(继承 BaseMapper)
├── service/
│ ├── UserService.java ← Service 接口
│ └── impl/UserServiceImpl.java ← Service 实现
└── controller/UserController.java ← Controller
src/main/resources/
└── mapper/
└── UserMapper.xml ← SQL 映射文件(可选)MyBatis Generatorの基本概念
MBGアーキテクチャ概要
┌──────────────────────────────────────────────────┐
│ MyBatis Generator │
│ │
│ ┌──────────┐ ┌───────────┐ ┌──────────────┐ │
│ │ Database │ │ Generator │ │ Generated │ │
│ │ Metadata │──→│ Engine │──→│ Code │ │
│ │ (JDBC) │ │ (Java) │ │ (Java/XML) │ │
│ └──────────┘ └─────┬─────┘ └──────────────┘ │
│ │ │
│ ┌────────┴────────┐ │
│ │ Configuration │ │
│ │ (XML / Java) │ │
│ └─────────────────┘ │
└──────────────────────────────────────────────────┘MBGワークフロー
-
generatorConfig.xmlまたはJava 構成を読み込みます。 -
JDBCを介してデータベースに接続し、テーブル、フィールド、プライマリ·キー、コメントなどのメタデータを読み込みます。
-
JDBC 型をJava 型に変換する。
-
エンティティークラス、Mapperインターフェイス、XMLマッピングファイル、およびオプションのExample 条件クラスを実行モードとテンプレートから生成します。
-
生成結果を指定したディレクトリに書き込みます。再生成前に上書きポリシーとマージポリシーを確認してください。XMLファイルのマージ動作に特に注意してください。
MBGバージョンの説明
MyBatis Generatorは1.4.xバージョンシリーズを使用します。この例では1.4.2を使用しており、バージョン番号は再現性を保証するために使用され、いつでも“最新バージョン”を表すものではありません。
Maven 座標ではorg.mybatis.generator:mybatis-generator-core:1.4.2を使用します。
環境準備と依存性
プロジェクトのディレクトリ構造
mybatis-generator-demo/
├── pom.xml
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/example/
│ │ │ ├── entity/
│ │ │ ├── mapper/
│ │ │ └── generator/
│ │ │ └── Generator.java
│ │ └── resources/
│ │ ├── generatorConfig.xml
│ │ └── mapper/
│ └── test/
└── lib/
└── mysql-connector-j-8.0.33.jarMaven 依存 pom.xml
<?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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>mybatis-generator-demo</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.16</version>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
</dependency>
<!-- MyBatis Generator 核心 -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.2</version>
</dependency>
<!-- Log4j2(可选,用于日志输出) -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.22.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- MyBatis Generator Maven 插件 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.2</version>
<configuration>
<!-- 配置文件路径 -->
<configurationFile>
src/main/resources/generatorConfig.xml
</configurationFile>
<!-- 是否覆盖已有文件 -->
<overwrite>true</overwrite>
<!-- 是否将 MBG 的输出打印到控制台 -->
<verbose>true</verbose>
</configuration>
<dependencies>
<!-- MySQL 驱动(插件也需要) -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>サンプル·データベース
-- 创建数据库
CREATE DATABASE IF NOT EXISTS mybatis_demo DEFAULT CHARSET utf8mb4;
USE mybatis_demo;
-- 部门表
CREATE TABLE dept (
dept_id INT PRIMARY KEY AUTO_INCREMENT COMMENT '部门ID',
dept_name VARCHAR(50) NOT NULL COMMENT '部门名称',
location VARCHAR(100) COMMENT '部门位置'
) COMMENT '部门表';
-- 员工表
CREATE TABLE emp (
emp_id INT PRIMARY KEY AUTO_INCREMENT COMMENT '员工ID',
emp_name VARCHAR(50) NOT NULL COMMENT '员工姓名',
gender CHAR(1) DEFAULT 'M' COMMENT '性别 M-男 F-女',
email VARCHAR(100) COMMENT '邮箱',
salary DECIMAL(10,2) COMMENT '工资',
dept_id INT COMMENT '所属部门ID',
hire_date DATE COMMENT '入职日期',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT
'更新时间',
FOREIGN KEY (dept_id) REFERENCES dept(dept_id)
) COMMENT '员工表';
-- 插入测试数据
INSERT INTO dept VALUES (1, '研发部', '北京'), (2, '市场部', '上海'), (3, '财务部', '广州');
INSERT INTO emp VALUES
(1, '张三', 'M', 'zhangsan@qq.com', 15000.00, 1, '2020-01-15', NOW(), NOW()),
(2, '李四', 'F', 'lisi@qq.com', 12000.00, 2, '2021-03-20', NOW(), NOW()),
(3, '王五', 'M', 'wangwu@qq.com', 18000.00, 1, '2019-07-01', NOW(), NOW());MBGの3つの動作モード
オプション1:Javaコードを実行する(柔軟なシナリオを推奨)
package com.example.generator;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.internal.DefaultShellCallback;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class Generator {
public static void main(String[] args) throws Exception {
List<String> warnings = new ArrayList<>();
boolean overwrite = true; // 是否覆盖已有文件
// 指向配置文件
File configFile = new File("src/main/resources/generatorConfig.xml");
ConfigurationParser parser = new ConfigurationParser(warnings);
Configuration config = parser.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator generator = new MyBatisGenerator(config, callback, warnings);
// 执行生成
generator.generate(null);
// 打印警告信息
for (String warning : warnings) {
System.out.println(warning);
}
System.out.println("✅ 代码生成完成!");
}
}実行方法: メインメソッドを右クリックして実行する。
方法 2:Mavenプラグインを実行する(通常のプロジェクト推奨)
pom.xmlでプラグインを構成したら、コマンドを実行します
# 在项目根目录执行
mvn mybatis-generator:generate
# 如果配置文件不在默认位置,指定路径
mvn mybatis-generator:generate -DconfigurationFile=src/main/resources/generatorConfig.xml
# 如果不想覆盖已有文件
mvn mybatis-generator:generate -Doverwrite=false
注: Mavenプラグインはデフォルトでsrc/main/resources/generatorConfig.xmlを読み込みます。構成ファイルがこのパスに置かれている場合、追加の指定は必要ありません。
オプション3:コマンドライン実行(スクリプト化に適しています)
# 1. 准备 mybatis-generator-core 和数据库驱动
# 2. 准备 generatorConfig.xml
# 3. 执行生成命令
java -jar mybatis-generator-core-1.4.2.jar -configfile generatorConfig.xml -overwrite
# 常用参数:
# -configfile 指定配置文件路径
# -overwrite 允许覆盖可覆盖的 Java 文件
# -verbose 输出详细信息3つの比較方法
| ** | Javaコード実行 | Mavenプラグイン | コマンドライン |
|---|---|---|---|
| 柔軟性がある。 | トップ(プログラマブルコントロール) | ミディアム·ミディアム | 最低レベルの |
| 複雑性の構成 | ミディアム·ミディアム | 低い。 | 低い。 |
| シーンに適して | カスタム論理が必要 | 日常の開発 | CI/CDスクリプト |
| IDEのサポート | ダイレクト·オペレーション | Mavenパネルクリック | 手動でJARを準備 |
generatorConfig.xml 構成の詳細
完全な構成テンプレート
<?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>
<!-- ① 引入外部属性文件 -->
<properties resource="generator.properties"/>
<!-- ② classPathEntry:指定数据库驱动路径(Maven插件方式可省略) -->
<classPathEntry location="lib/mysql-connector-j-8.0.33.jar"/>
<!-- ③ context:生成上下文(可配置多个) -->
<context id="mysqlContext" targetRuntime="MyBatis3"
defaultModelType="conditional">
<!-- ====== 内置插件配置 ====== -->
<!-- ④ 序列化插件(让实体类实现 Serializable) -->
<plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
<!-- ⑤ ToString 插件(生成 toString 方法) -->
<plugin type="org.mybatis.generator.plugins.ToStringPlugin"/>
<!-- ⑥ EqualsAndHashCode 插件 -->
<plugin type="org.mybatis.generator.plugins.EqualsAndHashCodePlugin"/>
<!-- ⑦ Row Bounds 插件(分页用,MySQL 不推荐) -->
<!-- <plugin type="org.mybatis.generator.plugins.RowBoundsPlugin"/> -->
<!-- ⑧ 虚拟主键插件 -->
<!-- <plugin type="org.mybatis.generator.plugins.VirtualKeyPlugin"/> -->
<!-- ====== 注释生成器 ====== -->
<!-- ⑨ 自定义注释生成器 -->
<commentGenerator>
<!-- 是否去除自动生成的注释 true:去除 false:保留 -->
<property name="suppressAllComments" value="false"/>
<!-- 是否生成注释中的日期 -->
<property name="suppressDate" value="true"/>
<!-- 是否添加数据库表的字段备注 -->
<property name="addRemarkComments" value="true"/>
</commentGenerator>
<!-- ====== 数据库连接 ====== -->
<!-- ⑩ JDBC 连接配置 -->
<jdbcConnection
driverClass="${jdbc.driver}"
connectionURL="${jdbc.url}"
userId="${jdbc.username}"
password="${jdbc.password}">
<!-- MySQL 8.x 需要设置以下属性,才能获取表注释 -->
<property name="useInformationSchema" value="true"/>
</jdbcConnection>
<!-- ====== 类型解析 ====== -->
<!-- ⑪ Java 类型解析器 -->
<javaTypeResolver>
<!-- 是否强制使用 BigDecimal -->
<property name="forceBigDecimals" value="false"/>
<!-- 是否使用 JSR-310 日期类型(java.time) -->
<property name="useJSR310Types" value="true"/>
</javaTypeResolver>
<!-- ====== 代码生成器 ====== -->
<!-- ⑫ Java 实体类生成器 -->
<javaModelGenerator
targetPackage="com.example.entity"
targetProject="src/main/java">
<!-- 是否让 schema 作为包的后缀 -->
<property name="enableSubPackages" value="false"/>
<!-- 从数据库返回的值是否清理前后的空格 -->
<property name="trimStrings" value="true"/>
<!-- 是否为实体类生成构造方法 -->
<property name="constructorBased" value="false"/>
<!-- 是否不可变(final 类,全参构造,无 setter) -->
<property name="immutable" value="false"/>
<!-- 父类(所有实体类继承的基类) -->
<!-- <property name="rootClass" value="com.example.BaseEntity"/> -->
</javaModelGenerator>
<!-- ⑬ SQL 映射文件生成器 -->
<sqlMapGenerator
targetPackage="mapper"
targetProject="src/main/resources">
<property name="enableSubPackages" value="false"/>
</sqlMapGenerator>
<!-- ⑭ Mapper 接口生成器 -->
<javaClientGenerator
type="XMLMAPPER"
targetPackage="com.example.mapper"
targetProject="src/main/java">
<property name="enableSubPackages" value="false"/>
<!-- 父接口(所有 Mapper 继承的接口) -->
<!-- <property name="rootInterface" value="com.example.BaseMapper"/> -->
</javaClientGenerator>
<!-- ====== 表配置 ====== -->
<!-- ⑮ table:每张表配置一个 -->
<table schema="mybatis_demo" tableName="emp"
domainObjectName="Emp"
enableCountByExample="true"
enableDeleteByExample="true"
enableSelectByExample="true"
enableUpdateByExample="true"
enableDeleteByPrimaryKey="true"
enableInsert="true"
enableSelectByPrimaryKey="true"
enableUpdateByPrimaryKey="true">
<!-- 主键策略:将自增主键回填到实体 -->
<generatedKey column="emp_id" sqlStatement="MySql" identity="true"/>
<!-- 列覆盖:强制指定某列的 Java 类型 -->
<!-- <columnOverride column="salary" property="salary"
javaType="java.math.BigDecimal"/> -->
<!-- 列忽略:不生成该字段 -->
<!-- <ignoreColumn column="create_time"/> -->
</table>
<table schema="mybatis_demo" tableName="dept"
domainObjectName="Dept"
enableCountByExample="true"
enableDeleteByExample="true"
enableSelectByExample="true"
enableUpdateByExample="true">
<generatedKey column="dept_id" sqlStatement="MySql" identity="true"/>
</table>
</context>
</generatorConfiguration>外部プロパティファイルgenerator.properties
# generator.properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_demo?useSSL=false&serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=123456
コンテキスト要素の詳細
contextプロパティ
<context>は、すべてのビルドルールが定義される構成の中核です。
<context id="mysqlContext"
targetRuntime="MyBatis3"
defaultModelType="conditional"
introspectedColumnImpl="org.mybatis.generator.internal.db.DatabaseIntrospector"
autoDelimitKeywords="false"
beginningDelimiter="`"
endingDelimiter="`">
| 属性 | 説明 | 共通値 |
|---|---|---|
id | 現在のコンテキストの一意の識別子 | 任意の重複しない文字列 |
targetRuntime | ジェネレータ動作モードの選択 | MyBatis3、MyBatis3Simple、MyBatis3DynamicSqlなど |
defaultModelType | 設置模型類構造 | conditional、flat、hierarchical |
autoDelimitKeywords | データベースキーワードに的に区切り文字を追加するかどうか | true、false |
beginningDelimiter | キーワード開始区切り文字 | My SQLは通常逆引用符 |
endingDelimiter | キーワード終了区切り文字 | MySQLでは通常逆引用符を使用する |
targetRuntimeの詳細
| 値 | 説明 | 生成物 |
|---|---|---|
| ミバティス3 | デフォルト、完全なコードを生成 | エンティティ+ Example + Mapper + XML Exampleメソッドを含む |
| MyBatis 3Simple | Exampleを生成しない簡易版 | エンティティー +マッパー + XML 基本 CRUDのみ |
| My Batis 3 Dynamics SQLの概要 | 動的 SQLバージョンMyBatis 3.4.0 以上が必要 | Entity + Mapper(DSL 使用、XMLなし) |
| MyBatis 3 Kotlin | Kotlinバージョン | Kotlin Entity + DSL Mapper |
MyBatis 3 Simpleで生成されたMapperメソッド(例なし):
insert()
deleteByPrimaryKey()
updateByPrimaryKey()
selectByPrimaryKey()
selectAll()
MyBatis3で生成されたMapperメソッド(例あり):
insert()
deleteByPrimaryKey()
updateByPrimaryKey()
selectByPrimaryKey()
selectAll() (Simple 没有)
countByExample()
deleteByExample()
selectByExample()
updateByExampleSelective()
updateByExample()defaultModelTypeの詳細
| 値 | 説明 | 使用シナリオ |
|---|---|---|
| conditional | デフォルトです。テーブルにプライマリ·キーが1つしかない場合はプライマリ·キー·クラスを生成せず、複合プライマリ·キーがある場合はプライマリ·キー·クラスを生成 | ほとんどのシーンは |
| flat(フラット) | すべてのテーブルはフラットなエンティティークラスを生成し、主キーもプレーンフィールドとして機能します。 | シンプルなテーブル。 |
| Hierarchical | 階層の生成:プライマリ·キー·クラス継承→ベース·エンティティークラス→ BLOB 付きクラス | BLOBフィールドのある複雑なテーブル |
階層パターンによって生成されるクラス構造:
Emp.java ← 继承 EmpKey,包含普通字段
EmpKey.java ← 仅包含主键字段
EmpWithBLOBs.java ← 继承 Emp,包含 BLOB 字段(如 TEXT/LONGTEXT)
jdbcConnection -データベース接続
基本構成
<jdbcConnection
driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis_demo?
useSSL=false&serverTimezone=Asia/Shanghai"
userId="root"
password="123456">
</jdbcConnection>
My SQL 8.x 特別設定
<jdbcConnection
driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis_demo"
userId="root"
password="123456">
<!-- ★ 关键:使用 information_schema 获取表/字段注释 -->
<property name="useInformationSchema" value="true"/>
<!-- 其他可选属性 -->
<property name="nullCatalogMeansCurrent" value="true"/>
<property name="characterEncoding" value="utf-8"/>
<property name="serverTimezone" value="Asia/Shanghai"/>
</jdbcConnection>重要: My SQL 8.xはデフォルトでテーブルコメントとフィールドコメントを返しません。useInformationSchema=trueを設定しないと、commentGeneratorのaddRemarkCommentsが無効になります。
データベース接続別構成リファレンス
<!-- MySQL 8.x -->
<jdbcConnection
driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis_demo?
useSSL=false&serverTimezone=Asia/Shanghai"
userId="root" password="123456">
<property name="useInformationSchema" value="true"/>
</jdbcConnection>
<!-- PostgreSQL -->
<jdbcConnection
driverClass="org.postgresql.Driver"
connectionURL="jdbc:postgresql://localhost:5432/mydb"
userId="postgres" password="123456"/>
<!-- Oracle -->
<jdbcConnection
driverClass="oracle.jdbc.OracleDriver"
connectionURL="jdbc:oracle:thin:@localhost:1521:orcl"
userId="scott" password="tiger"/>
<!-- SQL Server -->
<jdbcConnection
driverClass="com.microsoft.sqlserver.jdbc.SQLServerDriver"
connectionURL="jdbc:sqlserver://localhost:1433;databaseName=mydb"
userId="sa" password="123456"/>javaModelGenerator -エンティティークラス生成
基本構成
<javaModelGenerator
targetPackage="com.example.entity"
targetProject="src/main/java">
<!-- 是否让 schema 作为包名后缀 -->
<!-- true: com.example.entity.mybatis_demo.Emp -->
<!-- false: com.example.entity.Emp -->
<property name="enableSubPackages" value="false"/>
<!-- 是否清理从数据库返回的字符串前后的空格 -->
<property name="trimStrings" value="true"/>
<!-- 是否基于构造方法(生成全参构造 + setter) -->
<property name="constructorBased" value="false"/>
<!-- 是否生成不可变类(final + 全参构造 + 无 setter) -->
<property name="immutable" value="false"/>
<!-- 所有实体类的父类 -->
<!-- <property name="rootClass" value="com.example.BaseEntity"/> -->
</javaModelGenerator>生成されたエンティティークラスの例
構成 targetPackage=“com.example.entity” trimStrings=“true”
package com.example.entity;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
public class Emp {
private Integer empId;
private String empName;
private String gender;
private String email;
private BigDecimal salary;
private Integer deptId;
private LocalDate hireDate;
private LocalDateTime createTime;
private LocalDateTime updateTime;
// ====== 构造方法 ======
public Emp(Integer empId, String empName, String gender, String email,
BigDecimal salary, Integer deptId, LocalDate hireDate,
LocalDateTime createTime, LocalDateTime updateTime) {
this.empId = empId;
this.empName = empName == null ? null : empName.trim();
this.gender = gender;
this.email = email == null ? null : email.trim();
this.salary = salary;
this.deptId = deptId;
this.hireDate = hireDate;
this.createTime = createTime;
this.updateTime = updateTime;
}
public Emp() {
}
// ====== getter / setter ======
public Integer getEmpId() {
return empId;
}
public void setEmpId(Integer empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName == null ? null : empName.trim();
}
// ... 其他 getter/setter 省略 ...
}rootClassのサンプル
// BaseEntity.java — 所有实体类的父类
package com.example.entity;
import java.time.LocalDateTime;
public abstract class BaseEntity {
private LocalDateTime createTime;
private LocalDateTime updateTime;
// getter / setter
public LocalDateTime getCreateTime() { return createTime; }
public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime;
}
public LocalDateTime getUpdateTime() { return updateTime; }
public void setUpdateTime(LocalDateTime updateTime) { this.updateTime = updateTime;
}
}rootClassが設定された後、create_timeフィールドとupdate_timeフィールドはサブクラスで繰り返し生成されません。
sqlMapGenerator - XMLマッピングファイルの生成
基本構成
<sqlMapGenerator
targetPackage="mapper"
targetProject="src/main/resources">
<property name="enableSubPackages" value="false"/>
</sqlMapGenerator>
生成されたXMLサンプルMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.EmpMapper">
<resultMap id="BaseResultMap" type="com.example.entity.Emp">
<id column="emp_id" property="empId" jdbcType="INTEGER"/>
<result column="emp_name" property="empName" jdbcType="VARCHAR"/>
<result column="gender" property="gender" jdbcType="CHAR"/>
<result column="email" property="email" jdbcType="VARCHAR"/>
<result column="salary" property="salary" jdbcType="DECIMAL"/>
<result column="dept_id" property="deptId" jdbcType="INTEGER"/>
<result column="hire_date" property="hireDate" jdbcType="DATE"/>
<result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP"/>
</resultMap>
<!-- 通用列名 -->
<sql id="Base_Column_List">
emp_id, emp_name, gender, email, salary, dept_id, hire_date, create_time,
update_time
</sql>
<!-- 按主键查询 -->
<select id="selectByPrimaryKey" parameterType="java.lang.Integer"
resultMap="BaseResultMap">
SELECT
<include refid="Base_Column_List"/>
FROM emp
WHERE emp_id = #{empId,jdbcType=INTEGER}
</select>
<!-- 删除 -->
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
DELETE FROM emp
WHERE emp_id = #{empId,jdbcType=INTEGER}
</delete>
<!-- 插入 -->
<insert id="insert" parameterType="com.example.entity.Emp"
useGeneratedKeys="true" keyProperty="empId">
INSERT INTO emp (emp_name, gender, email,
salary, dept_id, hire_date,
create_time, update_time)
VALUES (#{empName,jdbcType=VARCHAR}, #{gender,jdbcType=CHAR},
#{email,jdbcType=VARCHAR}, #{salary,jdbcType=DECIMAL},
#{deptId,jdbcType=INTEGER}, #{hireDate,jdbcType=DATE},
#{createTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP})
</insert>
<!-- 选择性插入(null 字段不插入) -->
<insert id="insertSelective" parameterType="com.example.entity.Emp"
useGeneratedKeys="true" keyProperty="empId">
INSERT INTO emp
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="empName != null">emp_name,</if>
<if test="gender != null">gender,</if>
<if test="email != null">email,</if>
<if test="salary != null">salary,</if>
<if test="deptId != null">dept_id,</if>
<if test="hireDate != null">hire_date,</if>
<if test="createTime != null">create_time,</if>
<if test="updateTime != null">update_time,</if>
</trim>
<trim prefix="VALUES (" suffix=")" suffixOverrides=",">
<if test="empName != null">#{empName,jdbcType=VARCHAR},</if>
<if test="gender != null">#{gender,jdbcType=CHAR},</if>
<if test="email != null">#{email,jdbcType=VARCHAR},</if>
<if test="salary != null">#{salary,jdbcType=DECIMAL},</if>
<if test="deptId != null">#{deptId,jdbcType=INTEGER},</if>
<if test="hireDate != null">#{hireDate,jdbcType=DATE},</if>
<if test="createTime != null">#{createTime,jdbcType=TIMESTAMP},</if>
<if test="updateTime != null">#{updateTime,jdbcType=TIMESTAMP},</if>
</trim>
</insert>
<!-- 选择性更新 -->
<update id="updateByPrimaryKeySelective" parameterType="com.example.entity.Emp">
UPDATE emp
<set>
<if test="empName != null">emp_name = #{empName,jdbcType=VARCHAR},</if>
<if test="gender != null">gender = #{gender,jdbcType=CHAR},</if>
<if test="email != null">email = #{email,jdbcType=VARCHAR},</if>
<if test="salary != null">salary = #{salary,jdbcType=DECIMAL},</if>
<if test="deptId != null">dept_id = #{deptId,jdbcType=INTEGER},</if>
<if test="hireDate != null">hire_date = #{hireDate,jdbcType=DATE},</if>
<if test="createTime != null">create_time = #
{createTime,jdbcType=TIMESTAMP},</if>
<if test="updateTime != null">update_time = #
{updateTime,jdbcType=TIMESTAMP},</if>
</set>
WHERE emp_id = #{empId,jdbcType=INTEGER}
</update>
<!-- 全量更新 -->
<update id="updateByPrimaryKey" parameterType="com.example.entity.Emp">
UPDATE emp
SET emp_name = #{empName,jdbcType=VARCHAR},
gender = #{gender,jdbcType=CHAR},
email = #{email,jdbcType=VARCHAR},
salary = #{salary,jdbcType=DECIMAL},
dept_id = #{deptId,jdbcType=INTEGER},
hire_date = #{hireDate,jdbcType=DATE},
create_time = #{createTime,jdbcType=TIMESTAMP},
update_time = #{updateTime,jdbcType=TIMESTAMP}
WHERE emp_id = #{empId,jdbcType=INTEGER}
</update>
</mapper>javaClientGenerator - Mapperインタフェース生成
基本構成
<javaClientGenerator
type="XMLMAPPER"
targetPackage="com.example.mapper"
targetProject="src/main/java">
<property name="enableSubPackages" value="false"/>
</javaClientGenerator>
typeの特徴
| 値 | 説明 | 生成物 |
|---|---|---|
XMLMAPPER | インタフェースはXMLマッピングファイルから分離されており、ほとんどのプロジェクトに適している | MapperインタフェースとXML 対応 |
ANNOTATTEDMAPPER | SQLは主に注釈でインタフェースに記述される | Mapperインターフェイス、スタンドアロンXMLなし |
MIXEDMAPPER | 基礎文は注釈を使用し、複雑文はXMLを保持 | Mapperインターフェイスと部分 XML |
生成されたMapperインターフェイスの例(XMLMAPPERパターン)
package com.example.mapper;
import com.example.entity.Emp;
import com.example.entity.EmpExample;
import java.util.List;
import org.apache.ibatis.annotations.Param;
public interface EmpMapper {
// ====== 按 Example 查询 ======
long countByExample(EmpExample example);
int deleteByExample(EmpExample example);
List<Emp> selectByExample(EmpExample example);
int updateByExampleSelective(@Param("record") Emp record,
@Param("example") EmpExample example);
int updateByExample(@Param("record") Emp record,
@Param("example") EmpExample example);
// ====== 按主键操作 ======
int deleteByPrimaryKey(Integer empId);
int insert(Emp record);
int insertSelective(Emp record);
Emp selectByPrimaryKey(Integer empId);
int updateByPrimaryKeySelective(Emp record);
int updateByPrimaryKey(Emp record);
}ANNOTATEDMAPPERパターンによって生成されるインタフェース
// 纯注解,没有 XML 文件
public interface EmpMapper {
@Insert({
"INSERT INTO emp (emp_name, gender, ...)",
"VALUES (#{empName,jdbcType=VARCHAR}, #{gender,jdbcType=CHAR}, ...)"
})
@Options(useGeneratedKeys = true, keyProperty = "empId")
int insert(Emp record);
@Select({
"SELECT emp_id, emp_name, gender, ...",
"FROM emp",
"WHERE emp_id = #{empId,jdbcType=INTEGER}"
})
@ResultMap("BaseResultMap")
Emp selectByPrimaryKey(Integer empId);
// ... 其他方法
}テーブル要素の詳細
table 完全プロパティ
<table
schema="mybatis_demo" <!-- 数据库名/schema -->
tableName="emp" <!-- 数据库表名(支持通配符 %) -->
domainObjectName="Emp" <!-- 生成的实体类名 -->
mapperName="EmpMapper" <!-- 生成的 Mapper 接口名(可含包名) -->
sqlMapName="EmpMapper" <!-- 生成的 XML 文件名 -->
alias="e" <!-- 表别名(用于多表查询) -->
enableCountByExample="true" <!-- 是否生成 countByExample -->
enableDeleteByExample="true" <!-- 是否生成 deleteByExample -->
enableSelectByExample="true" <!-- 是否生成 selectByExample -->
enableUpdateByExample="true" <!-- 是否生成 updateByExample -->
enableDeleteByPrimaryKey="true" <!-- 是否生成 deleteByPrimaryKey -->
enableInsert="true" <!-- 是否生成 insert -->
enableSelectByPrimaryKey="true" <!-- 是否生成 selectByPrimaryKey -->
enableUpdateByPrimaryKey="true" <!-- 是否生成 updateByPrimaryKey -->
selectByPrimaryKeyQueryId="false"
selectByExampleQueryId="false"
modelType="conditional" <!-- 覆盖 context 的 defaultModelType -->
delimitIdentifiers="false" <!-- 是否给所有标识符加分隔符 -->
delimitAllColumns="false" <!-- 是否给所有列加分隔符 -->
>tableNameワイルドカードの使用法{{tableNameワイルドカードのしようほう}}
<!-- 生成所有表(慎用) -->
<table tableName="%"/>
<!-- 生成所有以 t_ 开头的表 -->
<table tableName="t_%" />
<!-- 排除某些表(需配合 table 的 schema 属性) -->
<table tableName="%" >
<!-- 通过 domainObjectRenamingRule 来调整命名 -->
</table>
generatedKey -プライマリ·キーのバックフィル
<table tableName="emp" domainObjectName="Emp">
<!-- 方式一:MySQL 自增主键 -->
<generatedKey column="emp_id" sqlStatement="MySql" identity="true"/>
<!-- 方式二:SQL Server 自增主键 -->
<!-- <generatedKey column="id" sqlStatement="SQL Server" identity="true"/> -->
<!-- 方式三:Oracle 序列 -->
<!-- <generatedKey column="id" sqlStatement="select SEQ_EMP.nextval from dual"
identity="false"/> -->
<!-- 方式四:PostgreSQL -->
<!-- <generatedKey column="id" sqlStatement="PostgreSQL" identity="true"/> -->
</table>| 属性 | 説明 |
|---|---|
n | プライマリ·キー·カラム名{{ぷらいまりきーからむ}} |
Statement | プライマリ·キー値を取得する文またはデータベースのID 例 MySQLでよく使われるMySql |
id | trueはデータベースの自己インクリメント·プライマリ·キーを示し、falseは文によってプライマリ·キーを取得することを示します。 |
typeは | preは挿入前にプライマリ·キーを取得し、postは挿入後にプライマリ·キーを取得する |
columnOverride - 列の上書き
<table tableName="emp" domainObjectName="Emp">
<!-- 强制指定某列的 Java 类型和 jdbcType -->
<columnOverride column="salary"
property="salary"
javaType="java.math.BigDecimal"
jdbcType="DECIMAL"/>
<!-- 强制指定枚举类型 -->
<columnOverride column="gender"
property="gender"
javaType="com.example.enums.Gender"
typeHandler="com.example.handler.GenderTypeHandler"/>
<!-- 修改属性名(驼峰自定义) -->
<columnOverride column="emp_name" property="name"/>
<!-- 强制 BLOB 类型 -->
<columnOverride column="content" isBlob="true" javaType="java.lang.String"/>
</table>ignoreColumn -列を無視する
<table tableName="emp" domainObjectName="Emp">
<!-- 不生成这些字段 -->
<ignoreColumn column="create_time"/>
<ignoreColumn column="update_time"/>
<!-- 支持正则匹配 -->
<!-- <ignoreColumn pattern="^temp_.*"/> -->
</table>
domainObjectRenamingRule -エンティティークラスの名前変更規則
<table tableName="t_emp" domainObjectName="Emp">
<!-- 去掉表名前缀 t_ -->
<domainObjectRenamingRule searchString="^T_" replaceString=""/>
</table>
columnRenamingRule - 列の名前変更規則
<table tableName="emp">
<!-- 去掉列名前缀 F_ -->
<columnRenamingRule searchString="^F_" replaceString=""/>
</table>
生成されたコード
完全なディレクトリ構造
mybatis-generator-demo/
├── src/main/java/com/example/
│ ├── entity/
│ │ ├── Emp.java ← 员工实体类
│ │ ├── EmpExample.java ← 员工查询条件类
│ │ ├── Dept.java ← 部门实体类
│ │ └── DeptExample.java ← 部门查询条件类
│ ├── mapper/
│ │ ├── EmpMapper.java ← 员工 Mapper 接口
│ │ └── DeptMapper.java ← 部门 Mapper 接口
│ └── generator/
│ └── Generator.java ← 生成器启动类
├── src/main/resources/
│ ├── generatorConfig.xml ← MBG 配置文件
│ ├── generator.properties ← 属性文件
│ ├── mapper/
│ │ ├── EmpMapper.xml ← 员工 SQL 映射
│ │ └── DeptMapper.xml ← 部门 SQL 映射
│ └── mybatis-config.xml ← MyBatis 主配置
└── pom.xml各方法の機能対照表
メソッド機能対応SQL
INSERT INTO emp(…)VALUES insert Emp recordすべてのフィールド…を挿入
insertSelective(Emp record)
選択的挿入 nullワードINSERT INTO emp… VALUESセグメントは挿入されません.. +
DELETE FROM emp WHERE emplify_id deleteByPrimaryKey Integer idプライマリ·キーによる削除=\
deleteByExample EmpExample example DELETE FROM emp WHERE ..
emp SET … WHERE updateByPrimaryKey(Emp record)emp_id =
updateByPrimaryKeySelective EmpUPDATE emp SET … WHERE 選択的更新 record emp_id = +
updateByExample… UPDATE emp SET ..。どこで…。
UPDATE emp SET ... WHERE ...
+ <if>
updateByExampleSelective…条件による选択的更新
SELECT … FROM emp WHERE selectByPrimaryKey Integer idプライマリ·キーによるemp_id =
SELECT ... FROM emp WHERE
...
selectByExample EmpExample example 条件によるクエリー
SELECT COUNT * FROM emp countByExample EmpExample example 条件によるカウントWHERE ..
Exampleクラスの詳細(QBCスタイルのクエリ)
Exampleクラスの
ExampleクラスはMBGによって自動的に生成された クエリ条件コンストラクタで、QBC Query By Criteria スタイルを採用し、チェーン呼び出しによってWHERE 条件を構築し、手書きのSQLを回避します。
Exampleクラス構造体
public class EmpExample {
protected String orderByClause; // 排序字段
protected boolean distinct; // 是否去重
protected List<Criteria> oredCriteria; // OR 条件列表
// 设置排序
public void setOrderByClause(String orderByClause) { ... }
// 设置去重
public void setDistinct(boolean distinct) { ... }
// 获取 OR 条件列表
public List<Criteria> getOredCriteria() { ... }
// 创建一个 OR 条件(相当于 OR (...))
public Criteria or() { ... }
// 添加一个 Criteria 到 OR 列表
public void or(Criteria criteria) { ... }
// 创建一个 Criteria(相当于一个 AND 条件组)
public Criteria createCriteria() { ... }
// = createCriteria(),内部调用
protected Criteria createCriteriaInternal() { ... }
// 清空所有条件
public void clear() { ... }
// ====== Criteria 内部类 ======
public abstract static class GeneratedCriteria {
// 等于
public Criteria andEmpIdEqualTo(Integer value) { ... }
// 不等于
public Criteria andEmpIdNotEqualTo(Integer value) { ... }
// 大于
public Criteria andEmpIdGreaterThan(Integer value) { ... }
// 大于等于
public Criteria andEmpIdGreaterThanOrEqualTo(Integer value) { ... }
// 小于
public Criteria andEmpIdLessThan(Integer value) { ... }
// 小于等于
public Criteria andEmpIdLessThanOrEqualTo(Integer value) { ... }
// IN
public Criteria andEmpIdIn(List<Integer> values) { ... }
// NOT IN
public Criteria andEmpIdNotIn(List<Integer> values) { ... }
// BETWEEN
public Criteria andEmpIdBetween(Integer value1, Integer value2) { ... }
// NOT BETWEEN
public Criteria andEmpIdNotBetween(Integer value1, Integer value2) { ... }
// LIKE
public Criteria andEmpNameLike(String value) { ... }
// NOT LIKE
public Criteria andEmpNameNotLike(String value) { ... }
// IS NULL
public Criteria andEmpNameIsNull() { ... }
// IS NOT NULL
public Criteria andEmpNameIsNotNull() { ... }
// ... 每个字段都有以上方法
}
// ====== Criteria 继承类 ======
public static class Criteria extends GeneratedCriteria {
// ...
}
}Example 一般的なクエリの例
// ====== 1. 查询所有 ======
List<Emp> allEmps = empMapper.selectByExample(new EmpExample());
// ====== 2. 按主键查询 ======
Emp emp = empMapper.selectByPrimaryKey(1);
// ====== 3. 等值查询:gender = 'M' ======
EmpExample example = new EmpExample();
example.createCriteria().andGenderEqualTo("M");
List<Emp> males = empMapper.selectByExample(example);
// ====== 4. 多条件 AND 查询 ======
// WHERE gender = 'M' AND salary > 10000 AND dept_id = 1
EmpExample example = new EmpExample();
example.createCriteria()
.andGenderEqualTo("M")
.andSalaryGreaterThan(new BigDecimal("10000"))
.andDeptIdEqualTo(1);
List<Emp> result = empMapper.selectByExample(example);
// ====== 5. OR 条件查询 ======
// WHERE (gender = 'M' AND salary > 15000) OR (gender = 'F' AND salary > 12000)
EmpExample example = new EmpExample();
example.createCriteria()
.andGenderEqualTo("M")
.andSalaryGreaterThan(new BigDecimal("15000"));
example.or()
.andGenderEqualTo("F")
.andSalaryGreaterThan(new BigDecimal("12000"));
List<Emp> result = empMapper.selectByExample(example);
// ====== 6. LIKE 查询 ======
// WHERE emp_name LIKE '%张%'
EmpExample example = new EmpExample();
example.createCriteria().andEmpNameLike("%张%");
List<Emp> result = empMapper.selectByExample(example);
// ====== 7. IN 查询 ======
// WHERE dept_id IN (1, 2, 3)
EmpExample example = new EmpExample();
example.createCriteria().andDeptIdIn(Arrays.asList(1, 2, 3));
List<Emp> result = empMapper.selectByExample(example);
// ====== 8. BETWEEN 查询 ======
// WHERE salary BETWEEN 8000 AND 20000
EmpExample example = new EmpExample();
example.createCriteria()
.andSalaryBetween(new BigDecimal("8000"), new BigDecimal("20000"));
List<Emp> result = empMapper.selectByExample(example);
// ====== 9. IS NULL 查询 ======
// WHERE email IS NULL
EmpExample example = new EmpExample();
example.createCriteria().andEmailIsNull();
List<Emp> result = empMapper.selectByExample(example);
// ====== 10. 排序 ======
// ORDER BY salary DESC
EmpExample example = new EmpExample();
example.setOrderByClause("salary DESC");
List<Emp> result = empMapper.selectByExample(example);
// ====== 11. 去重 ======
EmpExample example = new EmpExample();
example.setDistinct(true);
example.setOrderByClause("dept_id");
List<Emp> result = empMapper.selectByExample(example);
// ====== 12. 条件删除 ======
// DELETE FROM emp WHERE dept_id = 3
EmpExample example = new EmpExample();
example.createCriteria().andDeptIdEqualTo(3);
empMapper.deleteByExample(example);
// ====== 13. 条件更新 ======
// UPDATE emp SET salary = 20000 WHERE dept_id = 1
EmpExample example = new EmpExample();
example.createCriteria().andDeptIdEqualTo(1);
Emp record = new Emp();
record.setSalary(new BigDecimal("20000"));
empMapper.updateByExampleSelective(record, example);
// ====== 14. 条件计数 ======
EmpExample example = new EmpExample();
example.createCriteria().andGenderEqualTo("M");
long count = empMapper.countByExample(example);Example 比較表の使用
| 要件 | Exampleメソッド | SQLオペレータ |
|---|---|---|
| 等しい。 | andXxxEqualTo value | = |
| 等しくない。 | andXxxNotEqualTo value | ` |
| より大きい。 | andXxxGreaterThan value | ` |
| 以上に等しい | andXxxGreaterThanOrEqualTo value | > |
| より小さい。 | andXxxLessThan value | ```` |
| 以下のように | andXxxLessThanOrEqualTo value | <= |
| ファジーマッチ | andXxxLike value | LIKE |
| 非ファジーマッチング | andXxxNotLike value | NOT L |
| コレクションに含まれる | andXxxIn list | IN |
| コレクションは含まれない。 | andXxxNotIn list | NOT IN |
| 区間一致の意味 | andXxxBetween v1 v2 | BETWEEN |
| 空のために | andXxxIsNull | IS NULL |
| 空じゃない | andXxxIsNotNull | IS NOT NULL |
| OR 条件グループの追加 | example.or.andXxx... () | OR |
| ソート·ソート | example.setOrderByClause "xxx DESC" | `ORDER BY ‘ |
| 重さに。 | example.setDistinct true | DISTINCT |
カスタムCommentGeneratorコメントジェネレータ
default noteの問題点
MBGで生成されるデフォルトのコメント形式
/**
* This field was generated by MyBatis Generator.
* This field corresponds to the database column emp.emp_name
*
* @mbg.generated
*/
private String empName;
問題:コメントが役に立たない、データベースフィールドコメントがない、日付フォーマットがない。
CommentGeneratorをカスタマイズ
package com.example.generator;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.internal.DefaultCommentGenerator;
import java.util.Properties;
/**
* 自定义注释生成器
* 生成数据库字段注释到 Java 实体类中
*/
public class CustomCommentGenerator extends DefaultCommentGenerator {
private boolean addRemarkComments;
@Override
public void addConfigurationProperties(Properties properties) {
super.addConfigurationProperties(properties);
this.addRemarkComments = Boolean.parseBoolean(
properties.getProperty("addRemarkComments"));
}
/**
* 给字段添加注释(数据库列注释)
*/
@Override
public void addFieldComment(Field field,
IntrospectedTable introspectedTable,
IntrospectedColumn introspectedColumn) {
if (addRemarkComments) {
String remark = introspectedColumn.getRemarks();
if (remark != null && !remark.trim().isEmpty()) {
field.addJavaDocLine("/**");
field.addJavaDocLine(" * " + remark);
field.addJavaDocLine(" */");
}
}
}
/**
* 给类添加注释(表注释)
*/
@Override
public void addClassComment(InnerClass innerClass,
IntrospectedTable introspectedTable) {
String remark = introspectedTable.getRemarks();
innerClass.addJavaDocLine("/**");
if (remark != null && !remark.trim().isEmpty()) {
innerClass.addJavaDocLine(" * " + remark);
}
innerClass.addJavaDocLine(" * 对应数据库表: " +
introspectedTable.getFullyQualifiedTable());
innerClass.addJavaDocLine(" */");
}
/**
* 给 getter 方法添加注释
*/
@Override
public void addGetterComment(Method method,
IntrospectedTable introspectedTable,
IntrospectedColumn introspectedColumn) {
// 不生成 getter 注释(保持简洁)
}
/**
* 给 setter 方法添加注释
*/
@Override
public void addSetterComment(Method method,
IntrospectedTable introspectedTable,
IntrospectedColumn introspectedColumn) {
// 不生成 setter 注释(保持简洁)
}
}構成ファイルでのカスタム注釈ビルダーの使用
<context id="mysqlContext" targetRuntime="MyBatis3">
<!-- 使用自定义注释生成器 -->
<commentGenerator type="com.example.generator.CustomCommentGenerator">
<property name="suppressAllComments" value="false"/>
<property name="suppressDate" value="true"/>
<property name="addRemarkComments" value="true"/>
</commentGenerator>
<!-- ... 其他配置 ... -->
</context>生成されたエンティティークラスの効果
/**
* 员工表
* 对应数据库表: mybatis_demo.emp
*/
public class Emp {
/**
* 员工ID
*/
private Integer empId;
/**
* 员工姓名
*/
private String empName;
/**
* 性别 M-男 F-女
*/
private String gender;
// ... getter/setter
}プラグインのカスタマイズ
プラグインの仕組みの概要
MBGはプラグインメカニズムを介してコード生成プロセスの拡張を実装します。プラグインはビルドプロセスを傍受し、生成されたコードを変更または追加できます。
MBG 生成流程
↓
┌─────────────────────────────────┐
│ 阶段1: Model Class 生成 │ ← Plugin 可拦截
├─────────────────────────────────┤
│ 阶段2: SQL Map (XML) 生成 │ ← Plugin 可拦截
├─────────────────────────────────┤
│ 阶段3: Client (Mapper) 生成 │ ← Plugin 可拦截
├─────────────────────────────────┤
│ 阶段4: Example Class 生成 │ ← Plugin 可拦截
└─────────────────────────────────┘組み込みプラグインのリスト
| プラグインクラス | |
|---|---|
| SerializablePlugin | Serializableインタフェースを実装するエンティティークラス |
| ToStringPlugin | toStringメソッドの生成 |
| EqualsAndHashCode Plugin | equalsメソッドとhashCodeメソッドの生成 |
| RowBoundsPlugin | ページングメソッドの生成 RowBoundsベース、MySQLでは非推奨 |
| VirtualKeyPluginとは | 仮想プライマリ·キー·プラグイン |
| FluentBuilderMethods Plugin | 連鎖セッターを生成する(これを返す) |
| MapperNamePlugin | カスタムM 名 |
| RenameExampleClassPlugin | Exampleクラスの名前の変更 |
| CaseInsensitiveLikePlugin | 大文字と小文字を区別しないLIKEクエリ |
| UnmergeableXmlMapperPlugin | XMLは結合せず、直接上書き |
カスタムプラグインの例:Lombokプラグイン
生成されたエンティティークラスに、冗長なゲッター/セッターの代わりにLombokアノテーションを使用します:
package com.example.generator;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*;
import java.util.List;
/**
* 自定义 Lombok 插件
* 让生成的实体类使用 @Data 注解,去掉 getter/setter
*/
public class LombokPlugin extends PluginAdapter {
@Override
public boolean validate(List<String> warnings) {
return true;
}
/**
* 给实体类添加 Lombok 注解
*/
@Override
public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass,
IntrospectedTable introspectedTable)
{
// 添加 @Data 注解
topLevelClass.addImportedType("lombok.Data");
topLevelClass.addAnnotation("@Data");
// 添加 @Builder 注解(可选)
topLevelClass.addImportedType("lombok.Builder");
topLevelClass.addAnnotation("@Builder");
// 添加 @NoArgsConstructor
topLevelClass.addImportedType("lombok.NoArgsConstructor");
topLevelClass.addAnnotation("@NoArgsConstructor");
// 添加 @AllArgsConstructor
topLevelClass.addImportedType("lombok.AllArgsConstructor");
topLevelClass.addAnnotation("@AllArgsConstructor");
return true;
}
/**
* 给主键类添加 Lombok 注解(如果有)
*/
@Override
public boolean modelPrimaryKeyClassGenerated(TopLevelClass topLevelClass,
IntrospectedTable introspectedTable)
{
topLevelClass.addImportedType("lombok.Data");
topLevelClass.addAnnotation("@Data");
return true;
}
/**
* 禁止生成 getter 方法(由 Lombok @Data 提供)
*/
@Override
public boolean modelGetterMethodGenerated(Method method,
TopLevelClass topLevelClass,
IntrospectedColumn introspectedColumn,
IntrospectedTable introspectedTable,
ModelClassType modelClassType) {
return false; // false = 不生成 getter
}
/**
* 禁止生成 setter 方法
*/
@Override
public boolean modelSetterMethodGenerated(Method method,
TopLevelClass topLevelClass,
IntrospectedColumn introspectedColumn,
IntrospectedTable introspectedTable,
ModelClassType modelClassType) {
return false; // false = 不生成 setter
}
}設定でのカスタムプラグインの使用
<context id="mysqlContext" targetRuntime="MyBatis3">
<!-- 内置插件 -->
<plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
<plugin type="org.mybatis.generator.plugins.EqualsAndHashCodePlugin"/>
<!-- ★ 自定义 Lombok 插件 -->
<plugin type="com.example.generator.LombokPlugin"/>
<!-- ★ 重命名 Example 类为 Query -->
<plugin type="org.mybatis.generator.plugins.RenameExampleClassPlugin">
<property name="searchString" value="Example$"/>
<property name="replaceString" value="Query"/>
</plugin>
<!-- 自定义注释生成器 -->
<commentGenerator type="com.example.generator.CustomCommentGenerator">
<property name="suppressAllComments" value="false"/>
<property name="addRemarkComments" value="true"/>
</commentGenerator>
<!-- ... 其他配置 ... -->
</context>カスタムプラグインの例:Mapperが共通インターフェイスを継承
package com.example.generator;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.Interface;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import java.util.List;
/**
* 让所有生成的 Mapper 接口继承自定义的 BaseMapper
*/
public class BaseMapperPlugin extends PluginAdapter {
private String baseMapperPackage;
@Override
public boolean validate(List<String> warnings) {
baseMapperPackage = properties.getProperty("baseMapperPackage");
return baseMapperPackage != null && !baseMapperPackage.trim().isEmpty();
}
@Override
public boolean clientGenerated(Interface interfaze,
TopLevelClass topLevelClass,
IntrospectedTable introspectedTable) {
// 导入 BaseMapper
FullyQualifiedJavaType baseMapperType =
new FullyQualifiedJavaType(baseMapperPackage);
interfaze.addImportedType(baseMapperType);
// 让 Mapper 继承 BaseMapper<实体类>
FullyQualifiedJavaType entityType =
new FullyQualifiedJavaType(introspectedTable.getBaseRecordType());
interfaze.addSuperInterface(
new FullyQualifiedJavaType(baseMapperPackage + "<" +
entityType.getShortName() + ">"));
return true;
}
}
<plugin type="com.example.generator.BaseMapperPlugin">
<property name="baseMapperPackage" value="com.example.mapper.BaseMapper"/>
</plugin>MyBatis-Plusコードジェネレータ3.5.x+
MP Generatorの概要
MyBatis-PlusコードジェネレータはMBGよりも強力で、以下を生成できます。
- EntityエンティティークラスLomboker/ Swagger 注釈をサポート
- Mapperインタフェース(BaseMapperを継承)
- Mapper XMLマップファイル
- Serviceインタフェース+ Service 実装クラス{{Serviceいんたふぇ ーす+ Serviceじっこうくらす}}
- コントローラ(RESTfulインターフェイス付き)
依存性構成
<dependencies>
<!-- MyBatis-Plus(包含 MyBatis) -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.7</version>
</dependency>
<!-- MP 代码生成器核心 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.7</version>
</dependency>
<!-- 模板引擎(Freemarker / Velocity / Beetl 任选其一) -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.32</version>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
</dependency>
<!-- Lombok(可选) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.34</version>
<scope>provided</scope>
</dependency>
<!-- Swagger / SpringDoc(可选) -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.5.0</version>
</dependency>
</dependencies>高速ジェネレータ
MyBatis-Plus 3.5.3+は、チェーン構成でFastAutoGeneratorを提供します。
package com.example.generator;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.Collections;
public class MpGenerator {
public static void main(String[] args) {
FastAutoGenerator.create(
"jdbc:mysql://localhost:3306/mybatis_demo?
useSSL=false&serverTimezone=Asia/Shanghai",
"root",
"123456")
// ====== 全局配置 ======
.globalConfig(builder -> {
builder.author("example") // 作者
.outputDir("src/main/java") // 输出目录
.enableSwagger() // 开启 Swagger 注解
.commentDate("yyyy-MM-dd"); // 注释日期格式
})
// ====== 包配置 ======
.packageConfig(builder -> {
builder.parent("com.example") // 父包名
.entity("entity") // 实体类包名
.mapper("mapper") // Mapper 包名
.service("service") // Service 包名
.serviceImpl("service.impl") // Service 实现包名
.controller("controller") // Controller 包名
.xml("mapper") // XML 资源路径
.pathInfo(Collections.singletonMap(
OutputFile.xml,
"src/main/resources/mapper")); // XML 输出目录
})
// ====== 策略配置 ======
.strategyConfig(builder -> {
builder.addInclude("emp", "dept") // 表名(可变参数)
.addTablePrefix("t_", "sys_") // 过滤表前缀
.entityBuilder()
.naming(NamingStrategy.underline_to_camel) // 下划线转驼峰
.columnNaming(NamingStrategy.underline_to_camel)
.enableLombok() // 使用 Lombok
.enableTableFieldAnnotation() // 生成字段注解
.logicDeleteColumnName("deleted") // 逻辑删除字段
.versionColumnName("version") // 乐观锁字段
.idType(IdType.AUTO) // 主键策略
.formatFileName("%s") // 实体类名格式
.mapperBuilder()
.enableMapperAnnotation() // 生成 @Mapper 注解
.formatMapperFileName("%sMapper") // Mapper 文件名格式
.formatXmlFileName("%sMapper") // XML 文件名格式
.serviceBuilder()
.formatServiceFileName("%sService") // Service 接口名
.formatServiceImplFileName("%sServiceImpl") // Service 实现名
.controllerBuilder()
.enableRestStyle(); // 生成 @RestController
})
// ====== 模板引擎 ======
.templateEngine(new FreemarkerTemplateEngine())
// ====== 执行 ======
.execute();
System.out.println("✅ MyBatis-Plus 代码生成完成!");
}
}生成されたディレクトリ構造
src/main/java/com/example/
├── entity/
│ ├── Emp.java ← @Data + @TableName + 字段注解
│ └── Dept.java
├── mapper/
│ ├── EmpMapper.java ← extends BaseMapper<Emp>
│ └── DeptMapper.java
├── service/
│ ├── EmpService.java ← extends IService<Emp>
│ └── impl/
│ └── EmpServiceImpl.java ← extends ServiceImpl<EmpMapper, Emp>
└── controller/
├── EmpController.java ← @RestController
└── DeptController.java
src/main/resources/
└── mapper/
├── EmpMapper.xml
└── DeptMapper.xmlMyBatis-Plus Generatorの設定
AutoGeneratorの完全な構成 Fastモード以外
package com.example.generator;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
public class MpFullGenerator {
public static void main(String[] args) {
// ====== 1. 数据源配置 ======
DataSourceConfig dataSourceConfig = DataSourceConfig.builder(
"jdbc:mysql://localhost:3306/mybatis_demo?
useSSL=false&serverTimezone=Asia/Shanghai",
"com.mysql.cj.jdbc.Driver",
"root",
"123456")
.build();
// ====== 2. 全局配置 ======
GlobalConfig globalConfig = GlobalConfig.builder()
.author("example")
.outputDir("src/main/java")
.enableSwagger() // Swagger 注解
.disableOpenDir() // 生成后不自动打开目录
.commentDate("yyyy-MM-dd")
.dateType(DateType.TIME_PACK) // 使用 java.time 包
.build();
// ====== 3. 包配置 ======
PackageConfig packageConfig = PackageConfig.builder()
.parent("com.example")
.moduleName("system") // 模块名(会加到包路径中)
.entity("entity")
.mapper("mapper")
.service("service")
.serviceImpl("service.impl")
.controller("controller")
.xml("mapper.xml")
.pathInfo(java.util.Collections.singletonMap(
OutputFile.xml,
"src/main/resources/mapper"))
.build();
// ====== 4. 模板配置 ======
TemplateConfig templateConfig = TemplateConfig.builder()
.entity("templates/entity.java") // 使用自定义模板
.mapper("templates/mapper.java")
.xml("templates/mapper.xml")
.service("templates/service.java")
.serviceImpl("templates/serviceImpl.java")
.controller("templates/controller.java")
.build();
// ====== 5. 策略配置 ======
StrategyConfig strategyConfig = StrategyConfig.builder()
.addInclude("emp", "dept") // 要生成的表
.addTablePrefix("t_", "sys_") // 过滤表前缀
.addTableSuffix("_tab") // 过滤表后缀
// 实体策略
.entityBuilder()
.naming(NamingStrategy.underline_to_camel)
.columnNaming(NamingStrategy.underline_to_camel)
.enableLombok() // Lombok 注解
.enableTableFieldAnnotation() // @TableField 注解
.enableActiveRecord() // ActiveRecord 模式
.enableFileOverride() // 覆盖已有文件
.logicDeleteColumnName("deleted") // 逻辑删除
.versionColumnName("version") // 乐观锁
.idType(IdType.AUTO) // 主键策略
.formatFileName("%s") // 实体类名格式
.superClass("com.example.BaseEntity") // 父类
// Mapper 策略
.mapperBuilder()
.enableMapperAnnotation() // @Mapper 注解
.enableBaseResultMap() // 生成 BaseResultMap
.enableBaseColumnList() // 生成 BaseColumnList
.formatMapperFileName("%sMapper")
.formatXmlFileName("%sMapper")
// Service 策略
.serviceBuilder()
.formatServiceFileName("%sService")
.formatServiceImplFileName("%sServiceImpl")
.superServiceClass("com.example.BaseService")
.superServiceImplClass("com.example.BaseServiceImpl")
// Controller 策略
.controllerBuilder()
.enableRestStyle() // @RestController
.enableHyphenStyle() // URL 连字符风格
.formatFileName("%sController")
.build();
// ====== 6. 注入配置(自定义变量) ======
InjectionConfig injectionConfig = InjectionConfig.builder()
.customMap(java.util.Map.of(
"author", "example",
"version", "1.0.0"))
.build();
// ====== 7. 组装执行 ======
AutoGenerator generator = new AutoGenerator(dataSourceConfig);
generator.global(globalConfig);
generator.packageInfo(packageConfig);
generator.template(templateConfig);
generator.strategy(strategyConfig);
generator.injection(injectionConfig);
generator.templateEngine(new FreemarkerTemplateEngine());
generator.execute();
System.out.println("✅ 代码生成完成!");
}
}IdTypeプライマリ·キーポリシー
IdType値 | 説明 | 一般的なシーン |
|---|---|---|
AUTO | データベースのプライマリキーの使用 | MySQL AUTO_INCREMENTなど |
NONE | ローカルポリシーを指定せず、グローバル構成で処理 | プロジェクトによる統一構成 |
INPUT | 挿入前に開発者が手動で | ビジネス·プライマリ·キー |
ASSIGN_ID | デフォルト識別子ジェネレータを使用した長いIDの割り当て | 分散システム共通 |
ASSIGN_UUID | ハイフンなしのUUID 文字列の割り当て | 文字列プライマリ·キー |
NamingStrategy 命名戦略
| 値 | 説明 | サンプル |
|---|---|---|
underline_to_camel | 下線命名トランスキャメル命名 | emp_nameトランスempName |
no_change | データベース名の変更なし | emp_name emp_name |
データソース·タイプのマッピング
// MySQL 8.x 类型映射自定义
DataSourceConfig dataSourceConfig = DataSourceConfig.builder(
url, driver, username, password)
.typeConvert(new ITypeConvert() {
@Override
public IColumnType executeTypeConvert(TableInfo tableInfo, String fieldName,
String fieldType) {
// 自定义类型映射
if ("tinyint(1)".equalsIgnoreCase(fieldType)) {
return DbColumnType.BOOLEAN;
}
if ("json".equalsIgnoreCase(fieldType)) {
return DbColumnType.OBJECT;
}
// 默认使用 MP 内置映射
return TypeConverts.useDefault(tableInfo, fieldName, fieldType);
}
})
.build();テンプレートのカスタム化
カスタムエンティティークラステンプレート
MPはFreemarkerテンプレートエンジンを使用します。デフォルトのテンプレートは、myBatis-plus-generator jarパッケージ内のtemplates/ディレクトリにあります。
entity.java.ftlテンプレートをカスタマイズするには:
package ${package.Entity};
<#list table.importPackages as pkg>
import ${pkg};
</#list>
<#if swagger2>
import io.swagger.v3.oas.annotations.media.Schema;
</#if>
<#if entityLombokAnnotations>
import lombok.Data;
import lombok.experimental.Accessors;
</#if>
/**
* <p>
* ${table.comment!}
* </p>
*
* @author ${author}
* @since ${date}
*/
<#if entityLombokAnnotations>
@Data
@Accessors(chain = true)
</#if>
<#if swagger2>
@Schema(description = "${table.comment!}")
</#if>
@TableName("${schemaName}${table.name}")
public class ${entity} implements Serializable {
private static final long serialVersionUID = 1L;
<#-- ---------- BEGIN 字段循环遍历 ---------->
<#list table.fields as field>
<#if field.keyFlag>
<#if field.keyIdentityFlag>
@TableId(value = "${field.annotationColumnName}", type = IdType.AUTO)
<#elseif idType??>
@TableId(value = "${field.annotationColumnName}", type = IdType.${idType})
<#else>
@TableId(value = "${field.annotationColumnName}", type = IdType.ASSIGN_ID)
</#if>
<#elseif field.fill??>
<#-- 通用填充字段 -->
@TableField(value = "${field.annotationColumnName}", fill =
FieldFill.${field.fill})
<#elseif !field.propertyType?ends_with("Serializable")>
@TableField("${field.annotationColumnName}")
</#if>
<#if swagger2>
@Schema(description = "${field.comment!}")
</#if>
private ${field.propertyType} ${field.propertyName};
</#list>
<#------------ END 字段循环遍历 ---------->
<#if !entityLombokAnnotations>
<#list table.fields as field>
<#if field.propertyType == "boolean">
<#assign getprefix="is"/>
<#else>
<#assign getprefix="get"/>
</#if>
public ${field.propertyType} ${getprefix}${field.capitalPropertyName}() {
return ${field.propertyName};
}
public void set${field.capitalPropertyName}(${field.propertyType}
${field.propertyName}) {
this.${field.propertyName} = ${field.propertyName};
}
</#list>
</#if>
}カスタム定義テンプレートの操作
TemplateConfig templateConfig = TemplateConfig.builder()
.entity("/templates/my-entity.java") // 自定义模板路径
.mapper("/templates/my-mapper.java")
.xml("/templates/my-mapper.xml")
.service("/templates/my-service.java")
.serviceImpl("/templates/my-serviceImpl.java")
.controller("/templates/my-controller.java")
.build();
カスタム定義テンプレートをsrc/main/resources/templates/ディレクトリに置きます。
カスタムコントローラテンプレート(RESTfulスタイル)
package ${package.Controller};
import ${package.Entity}.${entity};
import ${package.Service}.${entity}Service;
<#if swagger2>
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
</#if>
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* <p>
* ${table.comment!} 前端控制器
* </p>
*
* @author ${author}
* @since ${date}
*/
<#if swagger2>
@Tag(name = "${table.comment!}")
</#if>
@RestController
@RequestMapping("/${table.entityPath}")
public class ${entity}Controller {
@Autowired
private ${entity}Service ${table.entityPath}Service;
@Operation(summary = "查询所有")
@GetMapping
public List<${entity}> list() {
return ${table.entityPath}Service.list();
}
@Operation(summary = "根据ID查询")
@GetMapping("/{id}")
public ${entity} getById(@PathVariable ${entity} ${table.entityPath}) {
return ${table.entityPath}Service.getById(${table.entityPath});
}
@Operation(summary = "新增")
@PostMapping
public boolean save(@RequestBody ${entity} ${table.entityPath}) {
return ${table.entityPath}Service.save(${table.entityPath});
}
@Operation(summary = "修改")
@PutMapping
public boolean update(@RequestBody ${entity} ${table.entityPath}) {
return ${table.entityPath}Service.updateById(${table.entityPath});
}
@Operation(summary = "根据ID删除")
@DeleteMapping("/{id}")
public boolean delete(@PathVariable ${entity} ${table.entityPath}) {
return ${table.entityPath}Service.removeById(${table.entityPath});
}
}Spring Bootの統合リバースエンジニアリング
Spring BootプロジェクトでのMBGの統合
pom.xml
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis Spring Boot Starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- MBG 插件 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.2</version>
<executions>
<!-- 可选:绑定到 generate-sources 阶段自动执行 -->
<execution>
<id>Generate MyBatis Artifacts</id>
<goals>
<goal>generate</goal>
</goals>
<!-- 取消注释则每次构建自动生成 -->
<!-- <phase>generate-sources</phase> -->
</execution>
</executions>
<configuration>
<configurationFile>
src/main/resources/generator/generatorConfig.xml
</configurationFile>
<overwrite>true</overwrite>
<verbose>true</verbose>
</configuration>
<dependencies>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>Spring Boot + MyBatis-Plusの統合
pom.xml:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>application.yml:
spring:
datasource:
url: jdbc:mysql://localhost:3306/mybatis_demo?
useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.example.entity
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
id-type: auto
logic-delete-field: deleted
logic-delete-value: 1
logic-not-delete-value: 0生成されたエンティティークラス使用例
// ====== Emp.java(MP 生成的实体类)======
@Schema(description = "员工表")
@TableName("emp")
@Data
@Accessors(chain = true)
public class Emp implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "员工ID")
@TableId(value = "emp_id", type = IdType.AUTO)
private Integer empId;
@Schema(description = "员工姓名")
@TableField("emp_name")
private String empName;
@Schema(description = "性别 M-男 F-女")
private String gender;
@Schema(description = "邮箱")
private String email;
@Schema(description = "工资")
private BigDecimal salary;
@Schema(description = "所属部门ID")
@TableField("dept_id")
private Integer deptId;
@Schema(description = "入职日期")
private LocalDate hireDate;
@Schema(description = "创建时间")
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@Schema(description = "更新时间")
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}
// ====== EmpMapper.java ======
@Mapper
public interface EmpMapper extends BaseMapper<Emp> {
// BaseMapper 已提供 insert/delete/update/select 等方法
// 可以在这里添加自定义 SQL
}
// ====== EmpService.java ======
public interface EmpService extends IService<Emp> {
// IService 已提供通用业务方法
// 可以在这里添加自定义业务方法
}
// ====== EmpServiceImpl.java ======
@Service
public class EmpServiceImpl extends ServiceImpl<EmpMapper, Emp> implements EmpService {
// ServiceImpl 已实现 IService 的所有方法
}
// ====== EmpController.java ======
@Tag(name = "员工管理")
@RestController
@RequestMapping("/emp")
public class EmpController {
@Autowired
private EmpService empService;
@Operation(summary = "分页查询")
@GetMapping("/page")
public Page<Emp> page(
@RequestParam(defaultValue = "1") Integer current,
@RequestParam(defaultValue = "10") Integer size) {
return empService.page(new Page<>(current, size));
}
@Operation(summary = "新增员工")
@PostMapping
public boolean save(@RequestBody Emp emp) {
return empService.save(emp);
}
@Operation(summary = "根据ID查询")
@GetMapping("/{id}")
public Emp getById(@PathVariable Integer id) {
return empService.getById(id);
}
@Operation(summary = "更新员工")
@PutMapping
public boolean update(@RequestBody Emp emp) {
return empService.updateById(emp);
}
@Operation(summary = "删除员工")
@DeleteMapping("/{id}")
public boolean delete(@PathVariable Integer id) {
return empService.removeById(id);
}
}マルチモジュールプロジェクトでのリバースエンジニアリング
マルチモジュールのプロジェクト構造
my-project/
├── pom.xml ← 父 POM
├── my-project-common/ ← 通用模块
│ └── pom.xml
├── my-project-entity/ ← 实体模块
│ ├── pom.xml
│ └── src/main/java/com/example/entity/
├── my-project-mapper/ ← Mapper 模块
│ ├── pom.xml
│ └── src/main/java/com/example/mapper/
├── my-project-service/ ← Service 模块
│ ├── pom.xml
│ └── src/main/java/com/example/service/
├── my-project-web/ ← Web 模块(启动模块)
│ ├── pom.xml
│ └── src/main/resources/
│ ├── generatorConfig.xml
│ └── application.yml
└── my-project-generator/ ← 代码生成器模块(独立)
├── pom.xml
└── src/main/java/com/example/Generator.javaマルチモジュールMBG 構成
<!-- generatorConfig.xml 放在 my-project-generator 模块中 -->
<generatorConfiguration>
<context id="multiModule" targetRuntime="MyBatis3">
<plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
<plugin type="org.mybatis.generator.plugins.ToStringPlugin"/>
<commentGenerator>
<property name="suppressAllComments" value="false"/>
</commentGenerator>
<jdbcConnection driverClass="${jdbc.driver}"
connectionURL="${jdbc.url}"
userId="${jdbc.username}"
password="${jdbc.password}">
<property name="useInformationSchema" value="true"/>
</jdbcConnection>
<javaTypeResolver>
<property name="useJSR310Types" value="true"/>
</javaTypeResolver>
<!-- 实体类输出到 entity 模块 -->
<javaModelGenerator
targetPackage="com.example.entity"
targetProject="../my-project-entity/src/main/java">
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- XML 输出到 web 模块的 resources -->
<sqlMapGenerator
targetPackage="mapper"
targetProject="../my-project-web/src/main/resources">
</sqlMapGenerator>
<!-- Mapper 接口输出到 mapper 模块 -->
<javaClientGenerator
type="XMLMAPPER"
targetPackage="com.example.mapper"
targetProject="../my-project-mapper/src/main/java">
</javaClientGenerator>
<table tableName="emp" domainObjectName="Emp">
<generatedKey column="emp_id" sqlStatement="MySql" identity="true"/>
</table>
</context>
</generatorConfiguration>クリティカル targetProjectは相対パスを使用します。./モジュール名/src/main/javaは、他のモジュールのソースディレクトリを指します。
マルチモジュールMP Generator
FastAutoGenerator.create(url, username, password)
.globalConfig(builder -> builder
.author("example")
.outputDir(System.getProperty("user.dir") + "/my-project-generator/src/main/java")
)
.packageConfig(builder -> builder
.parent("com.example")
// 实体类输出到 entity 模块
.entity("entity")
// Mapper 输出到 mapper 模块
.mapper("mapper")
.pathInfo(java.util.Map.of(
OutputFile.entity, "../my-project-entity/src/main/java",
OutputFile.mapper, "../my-project-mapper/src/main/java",
OutputFile.service, "../my-project-service/src/main/java",
OutputFile.serviceImpl, "../my-project-service/src/main/java",
OutputFile.controller, "../my-project-web/src/main/java",
OutputFile.xml, "../my-project-web/src/main/resources/mapper"
))
)
.strategyConfig(builder -> builder
.addInclude("emp", "dept")
.entityBuilder().enableLombok()
)
.execute();ケース1:MBG 完全プロジェクト
プロジェクト構築プロジェクト
# 1. 创建 Maven 项目
mvn archetype:generate -DgroupId=com.example -DartifactId=mbg-demo -DarchetypeArtifactId=maven-archetype-quickstart
# 2. 进入项目目录
cd mbg-demo
# 3. 添加依赖(参考 III 章节 pom.xml)
完全なプロファイル
generatorConfig.xml:
<?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>
<properties resource="generator.properties"/>
<context id="mysqlContext" targetRuntime="MyBatis3"
defaultModelType="conditional">
<!-- 插件 -->
<plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
<plugin type="org.mybatis.generator.plugins.ToStringPlugin"/>
<plugin type="org.mybatis.generator.plugins.EqualsAndHashCodePlugin"/>
<!-- 重命名 Example 为 Query -->
<plugin type="org.mybatis.generator.plugins.RenameExampleClassPlugin">
<property name="searchString" value="Example$"/>
<property name="replaceString" value="Query"/>
</plugin>
<!-- 注释生成器 -->
<commentGenerator>
<property name="suppressAllComments" value="false"/>
<property name="suppressDate" value="true"/>
<property name="addRemarkComments" value="true"/>
</commentGenerator>
<!-- 数据库连接 -->
<jdbcConnection driverClass="${jdbc.driver}"
connectionURL="${jdbc.url}"
userId="${jdbc.username}"
password="${jdbc.password}">
<property name="useInformationSchema" value="true"/>
</jdbcConnection>
<!-- 类型解析 -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
<property name="useJSR310Types" value="true"/>
</javaTypeResolver>
<!-- 实体类 -->
<javaModelGenerator
targetPackage="com.example.entity"
targetProject="src/main/java">
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- XML -->
<sqlMapGenerator
targetPackage="mapper"
targetProject="src/main/resources">
</sqlMapGenerator>
<!-- Mapper -->
<javaClientGenerator
type="XMLMAPPER"
targetPackage="com.example.mapper"
targetProject="src/main/java">
</javaClientGenerator>
<!-- 表配置 -->
<table tableName="emp" domainObjectName="Emp"
enableCountByExample="true"
enableDeleteByExample="true"
enableSelectByExample="true"
enableUpdateByExample="true">
<generatedKey column="emp_id" sqlStatement="MySql" identity="true"/>
</table>
<table tableName="dept" domainObjectName="Dept">
<generatedKey column="dept_id" sqlStatement="MySql" identity="true"/>
</table>
</context>
</generatorConfiguration>構築の実行
# 方式一:Maven 命令
mvn mybatis-generator:generate
# 方式二:运行 Java 类
# 直接运行 Generator.java 的 main 方法
テストの作成
package com.example.test;
import com.example.entity.Emp;
import com.example.entity.EmpQuery;
import com.example.mapper.EmpMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.List;
public class EmpMapperTest {
private SqlSession session;
private EmpMapper empMapper;
@Before
public void setUp() throws Exception {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
session = factory.openSession();
empMapper = session.getMapper(EmpMapper.class);
}
@After
public void tearDown() {
if (session != null) {
session.close();
}
}
// 测试1:插入
@Test
public void testInsert() {
Emp emp = new Emp();
emp.setEmpName("赵六");
emp.setGender("M");
emp.setEmail("zhaoliu@qq.com");
emp.setSalary(new BigDecimal("13000"));
emp.setDeptId(1);
int rows = empMapper.insert(emp);
System.out.println("插入行数: " + rows);
System.out.println("主键回填: " + emp.getEmpId());
session.commit();
}
// 测试2:按主键查询
@Test
public void testSelectByPrimaryKey() {
Emp emp = empMapper.selectByPrimaryKey(1);
System.out.println(emp);
}
// 测试3:条件查询
@Test
public void testSelectByExample() {
EmpQuery query = new EmpQuery();
query.createCriteria()
.andGenderEqualTo("M")
.andSalaryGreaterThan(new BigDecimal("10000"));
query.setOrderByClause("salary DESC");
List<Emp> list = empMapper.selectByExample(query);
list.forEach(System.out::println);
}
// 测试4:选择性更新
@Test
public void testUpdateByPrimaryKeySelective() {
Emp emp = new Emp();
emp.setEmpId(1);
emp.setSalary(new BigDecimal("20000"));
int rows = empMapper.updateByPrimaryKeySelective(emp);
System.out.println("更新行数: " + rows);
session.commit();
}
// 测试5:条件删除
@Test
public void testDeleteByExample() {
EmpQuery query = new EmpQuery();
query.createCriteria().andDeptIdIsNull();
int rows = empMapper.deleteByExample(query);
System.out.println("删除行数: " + rows);
session.commit();
}
// 测试6:条件计数
@Test
public void testCountByExample() {
EmpQuery query = new EmpQuery();
query.createCriteria().andGenderEqualTo("M");
long count = empMapper.countByExample(query);
System.out.println("男性员工数量: " + count);
}
}実際のケース2:MyBatis-Plus Generatorの完全なプロジェクト
プロジェクトの構築
<!-- pom.xml 关键依赖 -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.5.0</version>
</dependency>
</dependencies>ジェネレータのコード
package com.example.generator;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.HashMap;
import java.util.Map;
public class CodeGenerator {
public static void main(String[] args) {
// 数据库配置
String url = "jdbc:mysql://localhost:3306/mybatis_demo" +
"?
useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8";
String username = "root";
String password = "123456";
// 输出目录
String projectPath = System.getProperty("user.dir");
FastAutoGenerator.create(url, username, password)
.globalConfig(builder -> builder
.author("example")
.outputDir(projectPath + "/src/main/java")
.enableSwagger()
.commentDate("yyyy-MM-dd")
.disableOpenDir()
)
.packageConfig(builder -> {
Map<OutputFile, String> pathInfo = new HashMap<>();
pathInfo.put(OutputFile.xml, projectPath +
"/src/main/resources/mapper");
builder
.parent("com.example")
.entity("entity")
.mapper("mapper")
.service("service")
.serviceImpl("service.impl")
.controller("controller")
.pathInfo(pathInfo);
})
.strategyConfig(builder -> builder
.addInclude("emp", "dept") // 要生成的表
.addTablePrefix("t_", "sys_") // 去掉表前缀
.entityBuilder()
.naming(NamingStrategy.underline_to_camel)
.columnNaming(NamingStrategy.underline_to_camel)
.enableLombok()
.enableTableFieldAnnotation()
.idType(IdType.AUTO)
.logicDeleteColumnName("deleted")
.versionColumnName("version")
.formatFileName("%s")
.mapperBuilder()
.enableMapperAnnotation()
.enableBaseResultMap()
.enableBaseColumnList()
.formatMapperFileName("%sMapper")
.formatXmlFileName("%sMapper")
.serviceBuilder()
.formatServiceFileName("%sService")
.formatServiceImplFileName("%sServiceImpl")
.controllerBuilder()
.enableRestStyle()
.enableHyphenStyle()
.formatFileName("%sController")
)
.templateEngine(new FreemarkerTemplateEngine())
.execute();
System.out.println("✅ 代码生成完成!");
}
}オートフィルプロセッサー
package com.example.config;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* 自动填充处理器
* 配合实体类 @TableField(fill = FieldFill.INSERT) 使用
*/
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
// 新增时自动填充
this.strictInsertFill(metaObject, "createTime",
LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "updateTime",
LocalDateTime.class, LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
// 更新时自动填充
this.strictUpdateFill(metaObject, "updateTime",
LocalDateTime.class, LocalDateTime.now());
}
}ページング設定
package com.example.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 分页插件
interceptor.addInnerInterceptor(
new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}使用のテスト
package com.example.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.entity.Emp;
import com.example.service.EmpService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Tag(name = "员工管理")
@RestController
@RequestMapping("/emp")
public class EmpController {
@Autowired
private EmpService empService;
@Operation(summary = "分页查询")
@GetMapping("/page")
public Page<Emp> page(
@RequestParam(defaultValue = "1") Integer current,
@RequestParam(defaultValue = "10") Integer size) {
return empService.page(new Page<>(current, size));
}
@Operation(summary = "条件分页查询")
@GetMapping("/search")
public Page<Emp> search(
@RequestParam(defaultValue = "1") Integer current,
@RequestParam(defaultValue = "10") Integer size,
@RequestParam(required = false) String name,
@RequestParam(required = false) String gender,
@RequestParam(required = false) Integer deptId) {
Page<Emp> page = new Page<>(current, size);
return empService.lambdaQuery()
.like(name != null && !name.isEmpty(), Emp::getEmpName, name)
.eq(gender != null && !gender.isEmpty(), Emp::getGender, gender)
.eq(deptId != null, Emp::getDeptId, deptId)
.orderByDesc(Emp::getSalary)
.page(page);
}
@Operation(summary = "新增")
@PostMapping
public boolean save(@RequestBody Emp emp) {
return empService.save(emp);
}
@Operation(summary = "批量新增")
@PostMapping("/batch")
public boolean saveBatch(@RequestBody List<Emp> list) {
return empService.saveBatch(list);
}
@Operation(summary = "根据ID查询")
@GetMapping("/{id}")
public Emp getById(@PathVariable Integer id) {
return empService.getById(id);
}
@Operation(summary = "更新")
@PutMapping
public boolean update(@RequestBody Emp emp) {
return empService.updateById(emp);
}
@Operation(summary = "根据ID删除")
@DeleteMapping("/{id}")
public boolean delete(@PathVariable Integer id) {
return empService.removeById(id);
}
}実用例 3:カスタムプラグインがSwagger 注釈を生成する
需要は
MBGで生成されたエンティティークラスにSwagger/OpenAPI 注釈を自動的に追加させるには、次の手順に従います。
@Schema(description = "员工表")
public class Emp {
@Schema(description = "员工ID")
private Integer empId;
@Schema(description = "员工姓名")
private String empName;
}
Swaggerプラグインのカスタマイズ
package com.example.generator;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*;
import java.util.List;
/**
* 自定义 Swagger 注解插件
* 自动给实体类和字段添加 @Schema 注解
*/
public class SwaggerAnnotationPlugin extends PluginAdapter {
private static final String SCHEMA = "io.swagger.v3.oas.annotations.media.Schema";
@Override
public boolean validate(List<String> warnings) {
return true;
}
/**
* 给实体类添加 @Schema 注解
*/
@Override
public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass,
IntrospectedTable introspectedTable)
{
// 导入 @Schema
topLevelClass.addImportedType(SCHEMA);
// 生成注解:@Schema(description = "表注释")
String remark = introspectedTable.getRemarks();
String description = (remark != null && !remark.trim().isEmpty())
? remark
: introspectedTable.getFullyQualifiedTable().toString();
topLevelClass.addAnnotation("@Schema(description = \"" + escape(description) +
"\")");
return true;
}
/**
* 给字段添加 @Schema 注解
*/
@Override
public boolean modelFieldGenerated(Field field,
TopLevelClass topLevelClass,
IntrospectedColumn introspectedColumn,
IntrospectedTable introspectedTable,
ModelClassType modelClassType) {
// 确保 @Schema 已导入
if (!topLevelClass.getImportedTypes().stream()
.anyMatch(t -> t.getFullyQualifiedName().equals(SCHEMA))) {
topLevelClass.addImportedType(SCHEMA);
}
// 生成字段注解
String remark = introspectedColumn.getRemarks();
String description = (remark != null && !remark.trim().isEmpty())
? remark
: introspectedColumn.getActualColumnName();
field.addAnnotation("@Schema(description = \"" + escape(description) + "\")");
return true;
}
/**
* 转义特殊字符
*/
private String escape(String s) {
return s.replace("\"", "\\\"").replace("\n", " ").trim();
}
}使用の構成
<context id="mysqlContext" targetRuntime="MyBatis3">
<!-- ★ Swagger 注解插件 -->
<plugin type="com.example.generator.SwaggerAnnotationPlugin"/>
<!-- ★ Lombok 插件(配合使用) -->
<plugin type="com.example.generator.LombokPlugin"/>
<!-- Serializable -->
<plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
<commentGenerator>
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis_demo"
userId="root" password="123456">
<property name="useInformationSchema" value="true"/>
</jdbcConnection>
<javaTypeResolver>
<property name="useJSR310Types" value="true"/>
</javaTypeResolver>
<javaModelGenerator targetPackage="com.example.entity"
targetProject="src/main/java">
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<sqlMapGenerator targetPackage="mapper"
targetProject="src/main/resources">
</sqlMapGenerator>
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.example.mapper"
targetProject="src/main/java">
</javaClientGenerator>
<table tableName="emp" domainObjectName="Emp">
<generatedKey column="emp_id" sqlStatement="MySql" identity="true"/>
</table>
</context>生成されたエンティティークラスの効果
package com.example.entity;
import io.swagger.v3.oas.annotations.media.Schema;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "员工表")
public class Emp implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "员工ID")
private Integer empId;
@Schema(description = "员工姓名")
private String empName;
@Schema(description = "性别 M-男 F-女")
private String gender;
@Schema(description = "邮箱")
private String email;
@Schema(description = "工资")
private BigDecimal salary;
@Schema(description = "所属部门ID")
private Integer deptId;
@Schema(description = "入职日期")
private LocalDate hireDate;
@Schema(description = "创建时间")
private LocalDateTime createTime;
@Schema(description = "更新时间")
private LocalDateTime updateTime;
}よくある質問と間違い
生成後のテーブルコメントおよびフィールドコメントなし
理由: My SQL 8.xはデフォルトでコメント情報を返しません。
解決\<jdbcConnection>に<property name=“useInformationSchema” value=“true”/>を追加します。
<jdbcConnection ...>
<property name="useInformationSchema" value="true"/>
</jdbcConnection>
日付型はLocalDateTimeではなくDateを生成する
理由 デフォルトではjava.util.Dateを使用します。
解決済み<javaTypeResolver>でJSR-310をオンにします
<javaTypeResolver>
<property name="useJSR310Types" value="true"/>
</javaTypeResolver>
注:このプロパティはMBG 1.4.0+でのみサポートされます。DATETIME → Local DateTime,DATE → Local Date,TIME → Local Time.
ファイル上書きの問題:XMLファイルが完全に上書きされない
理由MBGはデフォルトでXMLファイルに対して完全な上書きではなくmergeマージ ポリシーを使用します。これは手書きのカスタムSQLを保護するためです。
解決済み UnmergeableXmlMapperPluginプラグインを使用して上書きを強制するには、次の手順に従います。
1<plugin type=“org.mybatis.generator.plugins.UnmergeableXmlMapperPlugin”/>
パッケージ名にはスキーマ名が追加されます
理由: enableSubPackagesがtrueに設定されている場合、スキーマ名がパッケージのサフィックスとして使用されます。
解決 enableSubPackages=“false”を設定します
<javaModelGenerator targetPackage="com.example.entity" ...>
<property name="enableSubPackages" value="false"/>
</javaModelGenerator>
プライマリ·キーがバックフィルされていないinsertの後、エンティティークラス内のidがnull
原因<generatedKey>が設定されていません。
解決済み:
<table tableName="emp" domainObjectName="Emp">
<generatedKey column="emp_id" sqlStatement="MySql" identity="true"/>
</table>
Mavenプラグインの実行時にドライバが見つかりません
原因: MavenプラグインのクラスパスにMy SQLドライバがありません。
解決:\<plugin>の<dependencies>にドライバを追加するには:
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.2</version>
<dependencies>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
</dependency>
</dependencies>
</plugin>MySQLキーワードのdesc、order、keyなど
理由: テーブル名またはフィールド名はMy SQL 予約語です。
解決: コンテキストで区切り文字を設定します:
<context id="mysqlContext" targetRuntime="MyBatis3"
autoDelimitKeywords="true"
beginningDelimiter="`"
endingDelimiter="`">
またはテーブルに設定します:
1<table tableName=“order” delimitIdentifiers=“true”>
MP Generatorが間違ったディレクトリにコードを生成
原因: outputDirパスが正しくありません。
回避 System.getProperty “user.dir”を使用して、パスが正しいことを確認します。
String projectPath = System.getProperty("user.dir");
FastAutoGenerator.create(url, username, password)
.globalConfig(builder -> builder
.outputDir(projectPath + "/src/main/java") // 绝对路径
)
...
MBGファイルの中国語文字化け
理由: コードが矛盾している。
解決 pom.xmlでエンコーディングを構成する
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
Maven Pluginの設定:
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<configuration>
<configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
</configuration>
</plugin>
MP Generator 3.5.xのAPI 変更点
問題: 3.4.xから3.5.xにアップグレードした後、APIの互換性がありません。
主な変更点
| 3.4.x 旧 | 3.5.x 新 |
|---|---|
| 新しいAutoGenerator | new AutoGenerator data |
| generator.setDataSource config | コンストラクタ引数の入力 |
| generator.setGlobalConfig config | gener.al config |
| generator.setStrategy config | generator.strategy config |
| generator.setPackageInfo config | generator.packageInfo config |
| generator.setTemplate config | generator.template config |
ベストプラクティスの例
ポリシーの選択の生成
是否需要 Service / Controller?
├── 是 → 使用 MyBatis-Plus Generator
│ (自带 Service / Controller / BaseMapper)
│
└── 否 → 使用 MyBatis Generator
(仅生成 Entity / Mapper / XML / Example)
生成コードとカスタムコードの分離
**コア原則:生成されたコードはいつでも再生成でき、直接変更することはできません。
正确的做法:
├── 生成的 Mapper 接口 ← 保持不变(继承 BaseMapper 扩展)
├── 自定义 SQL ← 新建 CustomXxxMapper.java 或在同一 XML 中追加
└── 业务逻辑 ← 写在 Service 层
错误的做法:
├── 直接在生成的 EmpMapper.java 中添加方法 ← 重新生成会被覆盖
├── 直接在生成的 EmpMapper.xml 中修改 SQL ← merge 可能保留,但有风险
└── 直接在生成的 Emp.java 中添加逻辑 ← 重新生成会被覆盖
XMLカスタムSQL 拡張スキーマ{{XMLかすたまいずSQLかくちょうすすきーま}}
<!-- EmpMapper.xml — MBG 生成的部分保持不变 -->
<!-- ====== 以下为手动追加的自定义 SQL ====== -->
<!-- 多表关联查询 -->
<select id="selectEmpWithDept" resultMap="EmpWithDeptResultMap">
SELECT e.*, d.dept_name, d.location
FROM emp e
LEFT JOIN dept d ON e.dept_id = d.dept_id
WHERE e.emp_id = #{empId}
</select>
<resultMap id="EmpWithDeptResultMap" type="com.example.dto.EmpDeptDTO">
<id column="emp_id" property="empId"/>
<result column="emp_name" property="empName"/>
<result column="gender" property="gender"/>
<result column="salary" property="salary"/>
<result column="dept_name" property="deptName"/>
<result column="location" property="location"/>
</resultMap>構成管理の推奨事項
项目结构建议:
├── src/main/resources/
│ ├── generator/
│ │ ├── generatorConfig.xml ← MBG 配置
│ │ ├── generator.properties ← 数据库连接属性
│ │ └── generator-dev.properties ← 开发环境属性(可选)
│ ├── mapper/
│ │ └── EmpMapper.xml ← 生成的 XML
│ └── mybatis-config.xml手書きの意思決定リストの作成
| シーン | 推奨方式 |
|---|---|
| 単一表 CRUD | リバースエンジニアリング生成 |
| 単一テーブル条件クエリ | MBGのExampleまたはMPのLambdaQueryWrapper |
| マルチテーブルJOINクエリー | 手书きSQL XMLまたは注记 |
| 複雑な統計レポート | 手書きSQL |
| ページングクエリ | MPページングプラグイン |
| 一括操作 | MP 用 saveBatch /updateBatchById |
クイックチェック·テーブル
MBG 構成要素のクイック·シート
| 元素 | 役割 | 必須 |
|---|---|---|
| <generatorConfiguration> | ルート 要素 | はい。 |
| <<プロパティ> | プロパティファイルの取り込み | いいえ、いいえ |
| < | データベース駆动パス | Maven 方式は節約 |
| “Context” | コンテキストの生成 | はい。 |
| <<プラグイン> | プラグインの設定 | いいえ、いいえ |
| <<コメントジェネレータ> | アノテーションビルダー | いいえ、いいえ |
| <jdbcConnection> | データベース接続 | はい。 |
| < | 型パーサー | いいえ、いいえ |
| <javaGenerator> | エンティティークラスジェネレータ | はい。 |
| <sqlMapGenerator> | XMLジェネレータ | XMLMAPPERスキーマ必須 |
| > | Mapperインターフェイス·ジェネレータ | はい。 |
| <<テーブル> | テーブルの構成 | はい。 |
MBG 内蔵プラグインスクイッチェックシート
| プラグイン | 機能 |
|---|---|
| SerializablePlugin | エンティティークラスSerializableの実装 |
| ToStringPlugin | toStringの生成 |
| EqualsAndHashCode Plugin | equalsおよびhashCodeの生成 |
| FluentBuilderMethods Plugin | チェーン·セッター |
| RowBoundsPlugin | RowBoundsページング |
| RenameExampleClassPlugin | Exampleクラスの名前の変更 |
| MapperNamePlugin | カスタムM 名 |
| UnmergeableXmlMapperPlugin | XML 強制オーバーライド |
| CaseInsensitiveLikePlugin | 大文字と小文字を区別しないLIKE |
| VirtualKeyPluginとは | 仮想プライマリキー |
MBG targetRuntimeクイック·シート
| 値 | の生成Example | の生成XML | の説明 |
|---|---|---|---|
| ミバティス3 | ↓ ↓ ↓ ↓ | ↓ ↓ ↓ ↓ | 完全版(デフォルト) |
| MyBatis 3Simple | CLARiX | ↓ ↓ ↓ ↓ | Liteバージョン基本 CRUDのみ |
| My Batis 3 Dynamics SQLの概要 | CLARiX | CLARiX | 動的 SQL DSLバージョン |
| MyBatis 3 Kotlin | CLARiX | CLARiX | Kotlinバージョン |
MP Generatorスケットシート
| 構成アイテム | 方法 | 説明 |
|---|---|---|
| 著者は | globalConfig.author “xxx” | コメント内の著者名 |
| 出力ディレクトリ | al | コードの出力ルート |
| スワッガー | globalConfig.enableSwagger | Swaggerコメントを開く |
| パターバッグ | packageConfig.parent “com.xxx” | ルートパケット名 |
| テーブルの名前 | strategyConfig.addInclude “table” | 生成するテーブルの指定 |
| テーブル接頭辞 | strategyConfig.addTablePrefix “t_“ | 表接頭辞の削除 |
| ロンボク | entityBuilder.enableLombok | ロンボックとは |
| プライマリ·キー·ポリシー | entityBuilder.idType IdType. | プライマリキー生成ポリシー |
| 命名ポリシー | entityBuilder.naming… | 下線回転こぶ |
| RestControllerのレビュー | controllerBuilder.enableRestStyle | RESTful |
Exampleメソッドクイック·テーブル{{Exampleめそっどすすぐてーす}}
EmpExample example = new EmpExample();
// 创建 AND 条件组
EmpExample.Criteria criteria = example.createCriteria();
// 等值
criteria.andXxxEqualTo(value); // = value
criteria.andXxxNotEqualTo(value); // <> value
// 范围
criteria.andXxxGreaterThan(value); // > value
criteria.andXxxGreaterThanOrEqualTo(value); // >= value
criteria.andXxxLessThan(value); // < value
criteria.andXxxLessThanOrEqualTo(value); // <= value
criteria.andXxxBetween(v1, v2); // BETWEEN v1 AND v2
criteria.andXxxNotBetween(v1, v2); // NOT BETWEEN
// 集合
criteria.andXxxIn(list); // IN (...)
criteria.andXxxNotIn(list); // NOT IN (...)
// 模糊
criteria.andXxxLike("%keyword%"); // LIKE '%keyword%'
criteria.andXxxNotLike("%keyword%"); // NOT LIKE '%keyword%'
// NULL
criteria.andXxxIsNull(); // IS NULL
criteria.andXxxIsNotNull(); // IS NOT NULL
// OR 条件组
example.or().andXxxEqualTo(value); // OR (...)
// 排序
example.setOrderByClause("salary DESC");
// 去重
example.setDistinct(true);タイプマッピングスケット
| MySQLタイプ | JavaタイプuseJSR310Types=true | JDBCタイプ |
|---|---|---|
INT | Integer | INTEGER |
BIGINT | Long | BIGINT |
TINYINT | Integer | TINYINT |
SMALLINT | Integer | SMALLINT |
DECIMAL | BigDecimal | DECIMAL |
VARCHAR | String | VARCHAR |
CHAR | String | CHAR |
TEXT | String | LONGVARCHAR |
DATE | LocalDate | DATE |
DATETIME | LocalDateTime | TIMESTAMP |
TIME | LocalTime | TIME |
TIMESTAMP | LocalDateTime | TIMESTAMP |
BLOB | byte[] | LONGVARBINARY |
BIT | Boolean | BIT |
FLOAT | Float | FLOAT |
DOUBLE | Double | DOUBLE |
JSON | String | VARCHAR |
共通コマンドのクイック·チェックリスト
# ====== MBG ======
# Maven 插件执行
mvn mybatis-generator:generate
# 指定配置文件
mvn mybatis-generator:generate -DconfigurationFile=src/main/resources/generatorConfig.xml
# 不覆盖已有文件
mvn mybatis-generator:generate -Doverwrite=false
# 命令行执行
java -jar mybatis-generator-core-1.4.2.jar -configfile generatorConfig.xml -overwrite
# ====== MP Generator ======
# 直接运行 main 方法(IDE 中右键运行)
# 或使用 Maven exec 插件
mvn exec:java -Dexec.mainClass="com.example.generator.CodeGenerator"**MyBatisのリバースエンジニアリングの中核は、データベーステーブル構造→ Javaコードの自動マッピングプロセスを理解することです。MyBatis Generatorは、基本的なDAO 層コードの生成に適した安定した公式ツールです。MyBatis-Plus Generatorは、EntityからControllerまでのフルスタックコードをワンクリックで生成する機能が豊富です。どちらもカスタムプラグインとテンプレートの詳細なカスタマイズにより結果を生成できます。リバースエンジニアリングをマスターすることで開発効率が大幅に向上しますが、再生成可能なコードはカスタムコードから分離し、再生成前にカバレッジを確認する必要があります。拡張クエリはスタンドアロンのMapper、拡張インターフェイス、またはカスタムSQLに配置できます。
気に入ったならばコメントを残してくださいね~