MyBatis-Plus模板生成🌸[新版]VS[旧版]

mp


遇到的问题

当我们要创建一个新项目时,根据MVC/三层架构的思想,我们要分层开发,需要根据数据库表创建对应的数据访问层业务实现层Web访问层(控制层),当然,还需要对应的对应的实体类进行封装。

在国内的话,MyBatis-Plus用的比较多,以User表举例的话,那么在初始话创建的时候:

  1. entity -> User实体类 -> @TableName指定表 @TableId指定主键信息 等

  2. mapper -> UserMapper -> public interface UserMapper extends BaseMapper {}

  3. service -> IUserServer -> public interface IUserService extends IService {}

  4. impl -> UserService ->

    @Service
    public class UserServiceImpl extends ServiceImpl<UserMapper, User>implements IUserService {

    }
  5. controller -> UserController ->

    @RestController
    @RequestMapping("/user")
    public class UserController {

    }

创建这些并不是很难,但是,如果表多了,那么创建这些却很繁琐,需要手动创建多个类/接口。

那么,有什么简单一点的方式呢?


新版模板生成器

那么就让我们用一下MyBatis-Plus模板生成器 [新版] 来实现一下吧

官方网站:MyBatis-Plus代码生成器配置-新版


要注意的是,新版的依赖是在3.5.X版本以上,这里使用的是3.5.1,旧版的模板依赖是org.freemarker,而新版使用的是velocity-engine-core的模板引擎,其次是是否需要使用Lombok,如果用的话builder.enableLombok() 开启Lombok

首先引入依赖

<!-- MyBatis-plus模板引擎 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<!-- 模板引擎 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
<!-- Lombok 可用 也可不用 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

接着你需要有几张测试得表:这里我用的是tb_blogtb_blogtb_shoptb_voucher四张表进行测试

image-20230402171921262



那为了以后回来 康却西康却喂修改,我进行了封装,直接把所有的代码写下来👇👇👇

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 java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class Temp {

//数据源的配置
private static final String url = "jdbc:mysql://地址:端口/数据库?useSSL=false&serverTimezone=UTC";
private static final String username = "username";
private static final String password = "password";

//一般配置这些即可
private static final String AUTHOR_NAME = "Ayaka-icu"; // 作者名字

private static final String PACKAGE_NAME = "icu.ayaka"; // 包名
//private static final String MODULE_NAME = ""; // 模块名 如果不用在下面代码中注释掉
private static final String DIR_NAME = "/src/main/java"; // 生成目录
private static final String MAP_NAME = "/src/main/resources/mapper"; // 生成mapper.xml目录
//如果A为父模块,当前模块为子模块B,在子模块B下运行生成模板,上面目录要加上模块路径
//private static final String DIR_NAME = "/B/src/main/java";
//private static final String MAP_NAME = "/B/src/main/resources/mapper";

//private static final String TBL_NAMES = "tb_user";
//设置表名👆 如果是多个表使用List集合👇 将这里注掉,打开下面的
private static final List<String> TBL_NAMES = Arrays.asList("tb_blog","tb_user","tb_shop","tb_voucher"); // 表名 如果是多个使用List集合

private static final String TABLE_PREFIX = "tb_"; // 表名的前缀,从表生成代码时会去掉前缀

public static void main(String[] args) {
FastAutoGenerator.create(url, username, password)
.globalConfig(builder -> {
builder.author(AUTHOR_NAME) // 设置作者
//.enableSwagger() // 启用swagger
// 指定输出目录
.outputDir(System.getProperty("user.dir") + DIR_NAME);
})
.packageConfig(builder -> {
builder //.moduleName(MODULE_NAME) // 模块名 可不用
//.other("dto") // 生成dto目录 可不用
.parent(PACKAGE_NAME)// 父包名。
.entity("entity") // 实体类包名
.controller("controller") // 控制层包名
.mapper("mapper") // mapper层包名
.service("service") // service层包名
.serviceImpl("service.impl") //service实现类包名
// 自定义mapper.xml文件输出目录
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, System.getProperty("user.dir") + "/src/main/resources/mapper"));
})
.strategyConfig(builder -> {
//设置要生成的表名
builder.addInclude(TBL_NAMES) // 表名
.addTablePrefix(TABLE_PREFIX) // 设置表前缀过滤
.entityBuilder()
.enableLombok() //开启Lombok
.enableChainModel()
.naming(NamingStrategy.underline_to_camel)//数据表映射实体命名策略:默认下划线转驼峰underline_to_camel
.columnNaming(NamingStrategy.underline_to_camel)//表字段映射实体属性命名规则:默认null,不指定按照naming执行
.idType(IdType.AUTO)//添加全局主键类型
.formatFileName("%s")//格式化实体名称,%s取消首字母I,
.mapperBuilder()
.enableMapperAnnotation()//开启mapper注解
.enableBaseResultMap()//启用xml文件中的BaseResultMap 生成
.enableBaseColumnList()//启用xml文件中的BaseColumnList
.formatMapperFileName("%sMapper")//格式化Dao类名称
.formatXmlFileName("%sMapper")//格式化xml文件名称
.serviceBuilder()
.formatServiceFileName("I%sService")//格式化 service 接口文件名称前面加I
.formatServiceImplFileName("%sServiceImpl")//格式化 service 接口文件名称
//.superServiceImplClass("I%sService")
.controllerBuilder()
.enableRestStyle();
}).execute();
// .injectionConfig(consumer -> {
// Map<String, String> customFile = new HashMap<>();
// // 配置DTO(需要的话)但是需要有能配置Dto的模板引擎,比如freemarker,但是这里我们用的VelocityEngine,因此不多作介绍
// customFile.put("DTO.java", "/templates/entityDTO.java.ftl");
// consumer.customFile(customFile);
// })
}
}

来看一下生成前的目录结构和文件

image-20230402173654371

开始运行

image-20230402174052157

image-20230402174119450


运行结束后,让我们看一下生成的 目录/接口/

image-20230402174421208

👇 目录 / 接口 / 类 👇

image-20230402174340870

image-20230402174808718


让我们看看生成tb_user相关的接口/

image-20230402175350589

那么,来写一段测试代码试试看

@RestController
@RequestMapping("/user")
public class UserController {

@Autowired
private IUserService userService;

@GetMapping("{id}")
public User getById(@PathVariable("id") Long id){
return userService.getById(id);
}

@GetMapping("/list")
public List<User> getList(){
return userService.list();
}
}

访问接口:

image-20230402180551222

image-20230402180554875

OK


旧版模板生成器

官方网站:MyBatis-Plus代码生成器配置-旧版

同样:要注意的是,旧版的依赖是在3.5.X版本以下,这里使用的是3.3.2,旧版的模板依赖是org.freemarker

新版的依赖不同:

<!-- MyBatis-plus模板引擎 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.3.2</version>
<!-- 注意要在 3.5.x 版本以下 -->
</dependency>

<!-- freemarke 模板 -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
<scope>compile</scope>
</dependency>

同样:那为了以后回来 康却西康却喂修改,我进行了封装,直接把所有的代码写下来👇👇👇


import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.util.*;

public class Temp {


// 数据源的配置
private static final String driver = "com.mysql.cj.jdbc.Driver"; //com.mysql.jdbc.Driver
private static final String url = "jdbc:mysql://地址:端口/数据库?useSSL=false&serverTimezone=UTC";
private static final String username = "username";
private static final String password = "password";

//一般配置这些即可
private static final String AUTHOR_NAME = "Ayaka-icu"; // 作者名字

private static final String PACKAGE_NAME = "icu.ayaka.es"; // 包名
//private static final String MODULE_NAME = ""; // 模块名 如果不用在下面代码中注释掉
private static final String DIR_NAME = "/src/main/java"; // 生成目录
private static final String MAP_NAME = "/src/main/resources/mapper/"; // 生成mapper.xml目录
//如果A为父模块,当前模块为子模块B,在子模块B下运行生成模板,上面目录要加上模块路径
//private static final String DIR_NAME = "/B/src/main/java";
//private static final String MAP_NAME = "/B/src/main/resources/mapper";

//表名 多个表使用英文逗号分割
private static final String TBL_NAMES = "tb_blog,tb_user,tb_voucher,tb_sign";

//表名的前缀 从表生成代码时会去掉前缀
private static final String TABLE_PREFIX = "tb_";

public static void main(String[] args) {

System.out.println("\n\n开始生成模板...\n\n");

// 0.代码生成器
AutoGenerator mpg = new AutoGenerator();

// 1.全局配置
GlobalConfig gc = getGlobalConfig();
mpg.setGlobalConfig(gc);

// 2.数据源配置
DataSourceConfig dsc = getDataSourceConfig();
mpg.setDataSource(dsc);

// 3.包配置
PackageConfig pc = getPackageConfig();
mpg.setPackageInfo(pc);

// 4.自定义配置
InjectionConfig cfg = getInjectionConfig();
mpg.setCfg(cfg);

// 5.模板配置
TemplateConfig templateConfig = getTemplateConfig();
mpg.setTemplate(templateConfig);
// 使用Freemarker模板引擎
mpg.setTemplateEngine(new FreemarkerTemplateEngine());

// 6.策略配置
StrategyConfig strategy = getStrategyConfig();
mpg.setStrategy(strategy);

// 7.开始生成代码
mpg.execute();
System.out.println("生成模板结束...");
}

// =======================================================================

// 1.全局配置
private static GlobalConfig getGlobalConfig() {
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath + DIR_NAME);
gc.setAuthor(AUTHOR_NAME);
gc.setOpen(false);
// 自定义生成的ServiceName,去掉默认的ServiceName前面的I
gc.setServiceName("I%s" + ConstVal.SERVICE);
// gc.setSwagger2(true); //实体属性 Swagger2 注解

return gc;
}

// 2.数据源配置
private static DataSourceConfig getDataSourceConfig() {
DataSourceConfig dsc = new DataSourceConfig();
dsc.setDriverName(driver);
dsc.setUrl(url);
// dsc.setSchemaName("public");
dsc.setUsername(username);
dsc.setPassword(password);
return dsc;
}

// 3.包配置
private static PackageConfig getPackageConfig() {
PackageConfig pc = new PackageConfig();
// 生成PACKAGE_NAME.MODULE_NAME的包路径
pc.setParent(PACKAGE_NAME);
//pc.setModuleName(MODULE_NAME);
return pc;
}

// 4.自定义配置
private static InjectionConfig getInjectionConfig() {

// 这里模板引擎使用的是freemarker
String templatePath = "/templates/mapper.xml.ftl";
// 自定义输出配置
List<FileOutConfig> focList = new ArrayList<>();
String projectPath = System.getProperty("user.dir");
// 自定义配置会被优先输出
focList.add(new FileOutConfig(templatePath) {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化
return projectPath + MAP_NAME + tableInfo.getEntityName() + "Mapper"
+ StringPool.DOT_XML;
}
});

InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
cfg.setFileOutConfigList(focList);
return cfg;
}

// 5.模板配置
private static TemplateConfig getTemplateConfig() {
TemplateConfig templateConfig = new TemplateConfig();

// 配置自定义输出模板
// 指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
// templateConfig.setEntity("templates/entity2.java");
// templateConfig.setService();
// templateConfig.setController();

templateConfig.setXml(null);
return templateConfig;
}

// 6.策略配置
private static StrategyConfig getStrategyConfig() {
StrategyConfig strategy = new StrategyConfig();
// 下划线转驼峰命名
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setEntityLombokModel(false);
strategy.setRestControllerStyle(true);
strategy.setInclude(TBL_NAMES.split(","));
strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix(TABLE_PREFIX);
return strategy;
}
}

效果一样。