在项目开发中,代码生成器能有效减少重复劳动,提高开发效率。以下基于提供的代码库,讲解两种常用代码生成方式:MyBatis 逆向工程 和自定义模板代码生成器。
一、MyBatis 逆向工程(数据库表→实体 / 映射文件)
1. 作用
根据数据库表结构自动生成:
- 实体类(Model)
- Mapper 接口(Dao 层)
- Mapper 映射文件(XML)
2. 核心代码与配置
(1)依赖配置(pom.xml)
xml
<!-- MyBatis逆向工程核心依赖 -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.6</version>
</dependency>
<!-- 数据库驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
(2)逆向工程配置文件(generatorConfig.xml)
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>
<context id="mybatisGenerator">
<!-- 去除自动生成的注释 -->
<commentGenerator>
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!-- 数据库连接配置 -->
<jdbcConnection
driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/ham?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai"
userId="root"
password="123456">
</jdbcConnection>
<!-- 类型解析器(DECIMAL/NUMERIC转Integer) -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- 生成实体类的路径 -->
<javaModelGenerator
targetPackage="com.qcby.model"
targetProject=".\hami_core\src\main\java">
<property name="trimStrings" value="true" /> <!-- 去除字符串前后空格 -->
</javaModelGenerator>
<!-- 生成Mapper映射文件的路径 -->
<sqlMapGenerator
targetPackage="mapper"
targetProject=".\hami_core\src\main\resources">
</sqlMapGenerator>
<!-- 生成Mapper接口的路径 -->
<javaClientGenerator
type="XMLMAPPER" <!-- 接口与XML分离模式 -->
targetPackage="com.qcby.dao"
targetProject=".\hami_core\src\main\java">
</javaClientGenerator>
<!-- 指定要生成的表(关闭Example相关方法,简化代码) -->
<table
tableName="album"
enableCountByExample="false"
enableUpdateByExample="false"
enableDeleteByExample="false"
enableSelectByExample="false"
selectByExampleQueryId="false"/>
</context>
</generatorConfiguration>
(3)执行类(Generator.java)
java
运行
package com.qcby.util;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class Generator {
public void generator() throws Exception {
List<String> warnings = new ArrayList<>();
boolean overwrite = true; // 允许覆盖已有文件
// 加载配置文件
File configFile = new File("hami_core/src/main/resources/generatorConfig.xml");
ConfigurationParser parser = new ConfigurationParser(warnings);
Configuration config = parser.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
// 执行生成
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
myBatisGenerator.generate(null);
}
// 入口方法
public static void main(String[] args) throws Exception {
try {
Generator generator = new Generator();
generator.generator();
} catch (Exception e) {
e.printStackTrace();
}
}
}
3. 生成结果说明
以album表为例,生成以下文件:
- 实体类 :
com.qcby.model.Album.java(包含字段、getter/setter) - Mapper 接口 :
com.qcby.dao.AlbumMapper.java(继承BaseDao<Album>) - 映射文件 :
resources/mapper/AlbumMapper.xml(包含 CRUD 的 SQL 语句)
二、自定义模板代码生成器(实体→Service / 实现类)
1. 作用
根据实体类名自动生成:
- Service 接口
- Service 实现类
- Mapper 接口(补充逆向工程未覆盖的逻辑)
2. 核心代码(SourceGenerator.java)
package com.qcby.util;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
/**
* 基于模板文件生成代码(通过IO流替换占位符)
*/
public class SourceGenerator {
// 入口方法:生成指定实体类的相关代码
public static void main(String[] args) throws Exception {
generatorSource("Songer"); // 生成Songer相关的Service和Dao
}
// 统一生成入口
public static void generatorSource(String objName) throws Exception {
generateDao(objName); // 生成Mapper接口
generateService(objName); // 生成Service接口
generateServiceImpl(objName); // 生成Service实现类
}
// 生成Mapper接口(基于DemoMapper.tpl模板)
public static void generateDao(String objName) throws Exception {
// 读取模板文件
BufferedReader br = new BufferedReader(new FileReader("hami_core/src/test/resources/tpl/DemoMapper.tpl"));
// 输出目标文件(如com/qcby/dao/SongerMapper.java)
BufferedWriter bw = new BufferedWriter(new FileWriter("hami_core/src/main/java/com/qcby/dao/" + objName + "Mapper.java"));
String line;
while ((line = br.readLine()) != null) {
line = line.replace("Demo", objName); // 替换占位符Demo为实体名
bw.write(line);
bw.newLine();
}
bw.close();
br.close();
}
// 生成Service接口(基于DemoService.tpl模板)
public static void generateService(String objName) throws Exception {
BufferedReader br = new BufferedReader(new FileReader("hami_core/src/test/resources/tpl/DemoService.tpl"));
BufferedWriter bw = new BufferedWriter(new FileWriter("hami_core/src/main/java/com/qcby/service/" + objName + "Service.java"));
String line;
while ((line = br.readLine()) != null) {
line = line.replace("Demo", objName);
bw.write(line);
bw.newLine();
}
bw.close();
br.close();
}
// 生成Service实现类(基于DemoServiceImpl.tpl模板)
public static void generateServiceImpl(String objName) throws Exception {
// 生成首字母小写的变量名(如Songer→songer)
String lowerObjName = objName.substring(0, 1).toLowerCase() + objName.substring(1);
BufferedReader br = new BufferedReader(new FileReader("hami_core/src/test/resources/tpl/DemoServiceImpl.tpl"));
BufferedWriter bw = new BufferedWriter(new FileWriter("hami_core/src/main/java/com/qcby/service/impl/" + objName + "ServiceImpl.java"));
String line;
while ((line = br.readLine()) != null) {
line = line.replace("Demo", objName); // 替换类名
line = line.replace("demo", lowerObjName); // 替换变量名
bw.write(line);
bw.newLine();
}
bw.close();
br.close();
}
}
3. 模板文件说明(以 Service 实现类为例)
假设DemoServiceImpl.tpl模板内容如下:
package com.qcby.service.impl;
import com.qcby.model.Demo;
import com.qcby.service.DemoService;
import com.qcby.dao.DemoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class DemoServiceImpl extends BaseServiceImpl<Demo> implements DemoService {
private DemoMapper demoMapper;
@Autowired
public void setDemoMapper(DemoMapper demoMapper) {
this.demoMapper = demoMapper;
this.baseDao = demoMapper;
}
}
生成SongerServiceImpl.java时,会自动替换:
Demo→Songer(类名)demo→songer(变量名)
三、两种生成方式对比
| 类型 | 输入 | 输出 | 适用场景 |
|---|---|---|---|
| MyBatis 逆向工程 | 数据库表 | 实体类、Mapper 接口 / XML | 数据库表结构→基础 CRUD 代码 |
| 自定义模板生成器 | 实体类名 | Service 接口 / 实现类、扩展 Mapper | 实体类→业务层模板代码 |
四、使用流程
-
通过逆向工程生成基础代码:
- 配置
generatorConfig.xml(指定数据库表) - 运行
Generator.main()生成实体类、Mapper 接口和 XML
- 配置
-
通过模板生成器补充业务层代码:
- 准备模板文件(
DemoMapper.tpl等) - 运行
SourceGenerator.main("实体类名")生成 Service 相关代码
- 准备模板文件(
-
扩展自定义方法:
- 在生成的接口中添加特殊业务方法(如
MtypeServiceImpl中的selectAll())
- 在生成的接口中添加特殊业务方法(如
通过代码生成器,可将重复的模板化代码自动生成,开发者只需关注核心业务逻辑,大幅提升开发效率。