原文网址:Mybatis-Plus--代码生成器/根据表生成代码--使用/教程/实例_IT利刃出鞘的博客-CSDN博客
说明
本文用实例介绍MybatisPlus的代码生成器。
MybatisPlus的代码生成器很好用,可以根据表来生成Entity、Mapper、Service、Controller,非常方便,只需要配置数据库信息然后运行代码即可。
默认就可以生成Entity、Mapper、Service、Controller,当然也可以自定义格式,本文将介绍默认格式的方法以及自定义格式的方法。
掌握了本文介绍的生成器的方法,可以将其应用到很多根据数据库生成代码的场景,比如:JPA等。
官网
代码生成器 | MyBatis-Plus
代码生成器配置 | MyBatis-Plus
创建表结构
pom.xml
因为我后边用的是freemarker(.ftl)作为模板,所以引入freemarker依赖。
后缀的含义:.ftl:freemarker;.vm:velocity;.btl:beetl。
其他两种格式的依赖为:
compile "org.apache.velocity:velocity-engine-core:2.2"
compile "com.ibeetl:beetl:3.1.8.RELEASE"
找到mybatis-plus-generater依赖包,查看它的模板文件:templates下边都是模板文件
本处使用.ftl文件(freemarker格式)进行修改。 修改后放到resources目录下的template_mp文件夹下
MyController.java.ftl
import org.springframework.web.bind.annotation.RequestMapping;
<#if restControllerStyle>
import org.springframework.web.bind.annotation.RestController;
<#else>
import org.springframework.stereotype.Controller;
#if>
<#if superControllerClassPackage??>
import ${superControllerClassPackage};
#if><#if restControllerStyle>
&#64;RestController
<#else>
&#64;Controller
#if>
&#64;RequestMapping("<#if package.ModuleName?? && package.ModuleName !&#61; "">/${package.ModuleName}#if>/<#if controllerMappingHyphenStyle??>${controllerMappingHyphen}<#else>${table.entityPath}#if>")
<#if kotlin>
class ${table.controllerName}<#if superControllerClass??> : ${superControllerClass}()#if>
<#else><#if superControllerClass??>
public class ${table.controllerName} extends ${superControllerClass} {<#else>
public class ${table.controllerName} {#if>}
#if>
MyService.java.ftl
import ${superServiceClassPackage};<#if kotlin>
interface ${table.serviceName} : ${superServiceClass}<${entity}>
<#else>
public interface ${table.serviceName} extends ${superServiceClass}<${entity}> {}
#if>
MyServiceImpl.java.ftl
import ${superServiceImplClassPackage};
import org.springframework.stereotype.Service;&#64;Service
<#if kotlin>
open class ${table.serviceImplName} : ${superServiceImplClass}<${table.mapperName}, ${entity}>(), ${table.serviceName} {}
<#else>
public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.mapperName}, ${entity}> implements ${table.serviceName} {}
#if>
MyMapper.java.ftl
import ${superMapperClassPackage};&#64;Repository
<#if kotlin>
interface ${table.mapperName} : ${superMapperClass}<${entity}>
<#else>
public interface ${table.mapperName} extends ${superMapperClass}<${entity}> {}
#if>
MyEntity.java.ftl
<#list table.importPackages as pkg>
import ${pkg};
#list>
<#if swagger2>
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
#if>
<#if entityLombokModel>
import lombok.Data;
import lombok.EqualsAndHashCode;<#if chainModel>
import lombok.experimental.Accessors;#if>
#if><#if entityLombokModel>
&#64;Data<#if superEntityClass??>
&#64;EqualsAndHashCode(callSuper &#61; true)<#else>
&#64;EqualsAndHashCode(callSuper &#61; false)#if><#if chainModel>
&#64;Accessors(chain &#61; true)#if>
#if>
<#if table.convert>
&#64;TableName("${table.name}")
#if>
<#if swagger2>
&#64;ApiModel(value&#61;"${entity}对象", description&#61;"${table.comment!}")
#if>
<#if superEntityClass??>
public class ${entity} extends ${superEntityClass}<#if activeRecord><${entity}>#if> {
<#elseif activeRecord>
public class ${entity} extends Model<${entity}> {
<#else>
public class ${entity} {
#if>
<#-- ---------- BEGIN 字段循环遍历 ---------->
<#list table.fields as field><#if field.keyFlag><#assign keyPropertyName&#61;"${field.propertyName}"/>#if><#if field.comment!?length gt 0><#if swagger2>&#64;ApiModelProperty(value &#61; "${field.comment}")<#else>// ${field.comment}#if>#if><#if field.keyFlag><#-- 主键 --><#if field.keyIdentityFlag>&#64;TableId(value &#61; "${field.annotationColumnName}", type &#61; IdType.AUTO)<#elseif idType??>&#64;TableId(value &#61; "${field.annotationColumnName}", type &#61; IdType.${idType})<#elseif field.convert>&#64;TableId("${field.annotationColumnName}")#if><#-- 普通字段 --><#elseif field.fill??><#-- ----- 存在字段填充设置 -----><#if field.convert>&#64;TableField(value &#61; "${field.annotationColumnName}", fill &#61; FieldFill.${field.fill})<#else>&#64;TableField(fill &#61; FieldFill.${field.fill})#if><#elseif field.convert>&#64;TableField("${field.annotationColumnName}")#if>
<#-- 乐观锁注解 --><#if (versionFieldName!"") &#61;&#61; field.name>&#64;Version#if>
<#-- 逻辑删除注解 --><#if (logicDeleteFieldName!"") &#61;&#61; field.name>&#64;TableLogic#if>private ${field.propertyType} ${field.propertyName};#list>
<#------------ END 字段循环遍历 ---------->
<#if !entityLombokModel><#list table.fields as field><#if field.propertyType &#61;&#61; "boolean"><#assign getprefix&#61;"is"/><#else><#assign getprefix&#61;"get"/>#if>public ${field.propertyType} ${getprefix}${field.capitalName}() {return ${field.propertyName};}<#if chainModel>public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {<#else>public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {#if>this.${field.propertyName} &#61; ${field.propertyName};<#if chainModel>return this;#if>}#list>
#if>
<#if entityColumnConstant><#list table.fields as field>public static final String ${field.name?upper_case} &#61; "${field.name}";#list>
#if>
<#if activeRecord>&#64;Overrideprotected Serializable pkVal() {<#if keyPropertyName??>return this.${keyPropertyName};<#else>return null;#if>}
#if>
<#if !entityLombokModel>&#64;Overridepublic String toString() {return "${entity}{" &#43;<#list table.fields as field><#if field_index&#61;&#61;0>"${field.propertyName}&#61;" &#43; ${field.propertyName} &#43;<#else>", ${field.propertyName}&#61;" &#43; ${field.propertyName} &#43;#if>#list>"}";}
#if>
}
controller.java.ftl
* ${table.comment!} 前端控制器* package ${package.Controller};import org.springframework.web.bind.annotation.RequestMapping;<#if restControllerStyle>
import org.springframework.web.bind.annotation.RestController;
<#else>
import org.springframework.stereotype.Controller;
#if>
<#if superControllerClassPackage??>
import ${superControllerClassPackage};
#if>/***
<#if restControllerStyle>
&#64;RestController
<#else>
&#64;Controller
#if>
&#64;RequestMapping("<#if package.ModuleName?? && package.ModuleName !&#61; "">/${package.ModuleName}#if>/<#if controllerMappingHyphenStyle??>${controllerMappingHyphen}<#else>${table.entityPath}#if>")
<#if kotlin>
class ${table.controllerName}<#if superControllerClass??> : ${superControllerClass}()#if>
<#else>
<#if superControllerClass??>
public class ${table.controllerName} extends ${superControllerClass} {
<#else>
public class ${table.controllerName} {
#if>}
#if>
service.java.ftl
* ${table.comment!} 服务类* package ${package.Service};import ${package.Entity}.${entity};
import ${superServiceClassPackage};/***
<#if kotlin>
interface ${table.serviceName} : ${superServiceClass}<${entity}>
<#else>
public interface ${table.serviceName} extends ${superServiceClass}<${entity}> {}
#if>
serviceImpl.java.ftl
* ${table.comment!} 服务实现类* package ${package.ServiceImpl};import ${package.Entity}.${entity};
import ${package.Mapper}.${table.mapperName};
import ${package.Service}.${table.serviceName};
import ${superServiceImplClassPackage};
import org.springframework.stereotype.Service;/***
&#64;Service
<#if kotlin>
open class ${table.serviceImplName} : ${superServiceImplClass}<${table.mapperName}, ${entity}>(), ${table.serviceName} {}
<#else>
public class ${table.serviceImplName} extends ${superServiceImplClass}<${table.mapperName}, ${entity}> implements ${table.serviceName} {}
#if>
mapper.java.ftl
* ${table.comment!} Mapper 接口* package ${package.Mapper};import ${package.Entity}.${entity};
import ${superMapperClassPackage};/***
<#if kotlin>
interface ${table.mapperName} : ${superMapperClass}<${entity}>
<#else>
public interface ${table.mapperName} extends ${superMapperClass}<${entity}> {}
#if>
entity.java.ftl
* ${table.comment!}* package ${package.Entity};<#list table.importPackages as pkg>
import ${pkg};
#list>
<#if swagger2>
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
#if>
<#if entityLombokModel>
import lombok.Data;
import lombok.EqualsAndHashCode;<#if chainModel>
import lombok.experimental.Accessors;#if>
#if>/***
<#if entityLombokModel>
&#64;Data<#if superEntityClass??>
&#64;EqualsAndHashCode(callSuper &#61; true)<#else>
&#64;EqualsAndHashCode(callSuper &#61; false)#if><#if chainModel>
&#64;Accessors(chain &#61; true)#if>
#if>
<#if table.convert>
&#64;TableName("${table.name}")
#if>
<#if swagger2>
&#64;ApiModel(value&#61;"${entity}对象", description&#61;"${table.comment!}")
#if>
<#if superEntityClass??>
public class ${entity} extends ${superEntityClass}<#if activeRecord><${entity}>#if> {
<#elseif activeRecord>
public class ${entity} extends Model<${entity}> {
<#else>
public class ${entity} implements Serializable {
#if><#if entitySerialVersionUID>private static final long serialVersionUID &#61; 1L;
#if>
<#-- ---------- BEGIN 字段循环遍历 ---------->
<#list table.fields as field><#if field.keyFlag><#assign keyPropertyName&#61;"${field.propertyName}"/>#if><#if field.comment!?length gt 0><#if swagger2>&#64;ApiModelProperty(value &#61; "${field.comment}")<#else>/*** ${field.comment}*/#if>#if><#if field.keyFlag><#-- 主键 --><#if field.keyIdentityFlag>&#64;TableId(value &#61; "${field.annotationColumnName}", type &#61; IdType.AUTO)<#elseif idType??>&#64;TableId(value &#61; "${field.annotationColumnName}", type &#61; IdType.${idType})<#elseif field.convert>&#64;TableId("${field.annotationColumnName}")#if><#-- 普通字段 --><#elseif field.fill??><#-- ----- 存在字段填充设置 -----><#if field.convert>&#64;TableField(value &#61; "${field.annotationColumnName}", fill &#61; FieldFill.${field.fill})<#else>&#64;TableField(fill &#61; FieldFill.${field.fill})#if><#elseif field.convert>&#64;TableField("${field.annotationColumnName}")#if><#-- 乐观锁注解 --><#if (versionFieldName!"") &#61;&#61; field.name>&#64;Version#if><#-- 逻辑删除注解 --><#if (logicDeleteFieldName!"") &#61;&#61; field.name>&#64;TableLogic#if>private ${field.propertyType} ${field.propertyName};
#list>
<#------------ END 字段循环遍历 ----------><#if !entityLombokModel><#list table.fields as field><#if field.propertyType &#61;&#61; "boolean"><#assign getprefix&#61;"is"/><#else><#assign getprefix&#61;"get"/>#if>public ${field.propertyType} ${getprefix}${field.capitalName}() {return ${field.propertyName};}<#if chainModel>public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {<#else>public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {#if>this.${field.propertyName} &#61; ${field.propertyName};<#if chainModel>return this;#if>}#list>
#if><#if entityColumnConstant><#list table.fields as field>public static final String ${field.name?upper_case} &#61; "${field.name}";#list>
#if>
<#if activeRecord>&#64;Overrideprotected Serializable pkVal() {<#if keyPropertyName??>return this.${keyPropertyName};<#else>return null;#if>}#if>
<#if !entityLombokModel>&#64;Overridepublic String toString() {return "${entity}{" &#43;<#list table.fields as field><#if field_index&#61;&#61;0>"${field.propertyName}&#61;" &#43; ${field.propertyName} &#43;<#else>", ${field.propertyName}&#61;" &#43; ${field.propertyName} &#43;#if>#list>"}";}
#if>
}
package com.example.generate;import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;public class Generate {private static final String url &#61; "jdbc:mysql://127.0.0.1:3306/blog" &#43;"?useUnicode&#61;true&characterEncoding&#61;utf8" &#43;"&allowPublicKeyRetrieval&#61;True&useSSL&#61;false" &#43;"&serverTimezone&#61;Asia/Shanghai";private static final String userName &#61; "root";private static final String password &#61; "222333";private static final String tableName &#61; "t_blog";private static final String tablePrefix &#61; "t_";// 演示例子public static void main(String[] args) {// 代码生成器AutoGenerator autoGenerator &#61; new AutoGenerator();// 全局配置GlobalConfig globalConfig &#61; new GlobalConfig();String projectPath &#61; System.getProperty("user.dir");globalConfig.setOutputDir(projectPath &#43; "/src/main/java");globalConfig.setAuthor("xxx");globalConfig.setFileOverride(false); //默认就是falseglobalConfig.setOpen(false);// gc.setBaseResultMap(true); // mapper.xml 生成 ResultMap// gc.setBaseColumnList(true); // mapper.xml 生成 ColumnList// 自定义文件命名&#xff0c;注意 %s 会自动填充表实体属性&#xff01;globalConfig.setMapperName("%sMapper");// gc.setXmlName("%sDao");globalConfig.setServiceName("%sService");globalConfig.setServiceImplName("%sServiceImpl");globalConfig.setControllerName("%sController");// gc.setSwagger2(true); 实体属性 Swagger2 注解autoGenerator.setGlobalConfig(globalConfig);// 数据源配置DataSourceConfig dataSourceConfig &#61; new DataSourceConfig();dataSourceConfig.setUrl(url);// dsc.setSchemaName("public");dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");dataSourceConfig.setUsername(userName);dataSourceConfig.setPassword(password);autoGenerator.setDataSource(dataSourceConfig);// 包配置PackageConfig packageConfig &#61; new PackageConfig();// pc.setParent("com.example.generate.out");// pc.setModuleName("xxx");packageConfig.setParent("com.example.generate." &#43; tableName.substring(tablePrefix.length()));autoGenerator.setPackageInfo(packageConfig);// 自定义配置// InjectionConfig cfg &#61; new InjectionConfig() {// &#64;Override// public void initMap() {// // to do nothing// }// };// 配置自定义输出模板TemplateConfig templateConfig &#61; new TemplateConfig();//指定自定义模板路径&#xff0c;注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别templateConfig.setController("templates_mp/MyController.java");templateConfig.setService("templates_mp/MyService.java");templateConfig.setServiceImpl("templates_mp/MyServiceImpl.java");templateConfig.setMapper("templates_mp/MyMapper.java");templateConfig.setEntity("templates_mp/MyEntity.java");templateConfig.setXml(null);autoGenerator.setTemplate(templateConfig);// 策略配置StrategyConfig strategyConfig &#61; new StrategyConfig();strategyConfig.setNaming(NamingStrategy.underline_to_camel);strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);//strategy.setSuperEntityClass("你自己的父类实体,没有就不用设置!");strategyConfig.setEntityLombokModel(true);strategyConfig.setRestControllerStyle(true);// 公共父类// strategy.setSuperControllerClass("你自己的父类控制器,没有就不用设置!");// 写于父类中的公共字段// strategy.setSuperEntityColumns("id");// 表名strategyConfig.setInclude(tableName);strategyConfig.setTablePrefix(tablePrefix);autoGenerator.setStrategy(strategyConfig);strategyConfig.setControllerMappingHyphenStyle(true);autoGenerator.setTemplateEngine(new FreemarkerTemplateEngine());autoGenerator.execute();}
}
将“步骤3”代码放到任意位置运行即可。
运行之前
运行之后
红框中是新生成的文件
创建表结构
步骤2&#xff1a;引入依赖
compile "com.baomidou:mybatis-plus-generator:3.4.0"
compile "org.slf4j:slf4j-api:1.7.30"
compile "org.slf4j:slf4j-simple:1.7.30"
compile "mysql:mysql-connector-java:8.0.21"
package com.example.generate;import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;public class Generate {private static final String url &#61; "jdbc:mysql://127.0.0.1:3306/blog" &#43;"?useUnicode&#61;true&characterEncoding&#61;utf8" &#43;"&allowPublicKeyRetrieval&#61;True&useSSL&#61;false" &#43;"&serverTimezone&#61;Asia/Shanghai";private static final String userName &#61; "root";private static final String password &#61; "222333";private static final String tableName &#61; "t_blog";private static final String tablePrefix &#61; "t_";// 演示例子public static void main(String[] args) {// 代码生成器AutoGenerator autoGenerator &#61; new AutoGenerator();// 全局配置GlobalConfig globalConfig &#61; new GlobalConfig();String projectPath &#61; System.getProperty("user.dir");globalConfig.setOutputDir(projectPath &#43; "/src/main/java");globalConfig.setAuthor("xxx");globalConfig.setFileOverride(false); //默认就是falseglobalConfig.setOpen(false);// gc.setBaseResultMap(true); // mapper.xml 生成 ResultMap// gc.setBaseColumnList(true); // mapper.xml 生成 ColumnList// 自定义文件命名&#xff0c;注意 %s 会自动填充表实体属性&#xff01;globalConfig.setMapperName("%sMapper");// gc.setXmlName("%sDao");globalConfig.setServiceName("%sService");globalConfig.setServiceImplName("%sServiceImpl");globalConfig.setControllerName("%sController");// gc.setSwagger2(true); 实体属性 Swagger2 注解autoGenerator.setGlobalConfig(globalConfig);// 数据源配置DataSourceConfig dataSourceConfig &#61; new DataSourceConfig();dataSourceConfig.setUrl(url);// dsc.setSchemaName("public");dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");dataSourceConfig.setUsername(userName);dataSourceConfig.setPassword(password);autoGenerator.setDataSource(dataSourceConfig);// 包配置PackageConfig packageConfig &#61; new PackageConfig();// pc.setParent("com.example.generate.out");// pc.setModuleName("xxx");packageConfig.setParent("com.example.generate." &#43; tableName.substring(tablePrefix.length()));autoGenerator.setPackageInfo(packageConfig);// 自定义配置// InjectionConfig cfg &#61; new InjectionConfig() {// &#64;Override// public void initMap() {// // to do nothing// }// };// // 配置自定义输出模板// TemplateConfig templateConfig &#61; new TemplateConfig();// //指定自定义模板路径&#xff0c;注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别// templateConfig.setController("templates_mp/MyController.java");// templateConfig.setService("templates_mp/MyService.java");// templateConfig.setServiceImpl("templates_mp/MyServiceImpl.java");// templateConfig.setMapper("templates_mp/MyMapper.java");// templateConfig.setEntity("templates_mp/MyEntity.java");// templateConfig.setXml(null);// autoGenerator.setTemplate(templateConfig);// 策略配置StrategyConfig strategyConfig &#61; new StrategyConfig();strategyConfig.setNaming(NamingStrategy.underline_to_camel);strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);//strategy.setSuperEntityClass("你自己的父类实体,没有就不用设置!");strategyConfig.setEntityLombokModel(true);strategyConfig.setRestControllerStyle(true);// 公共父类// strategy.setSuperControllerClass("你自己的父类控制器,没有就不用设置!");// 写于父类中的公共字段// strategy.setSuperEntityColumns("id");// 表名strategyConfig.setInclude(tableName);strategyConfig.setTablePrefix(tablePrefix);autoGenerator.setStrategy(strategyConfig);strategyConfig.setControllerMappingHyphenStyle(true);autoGenerator.setTemplateEngine(new FreemarkerTemplateEngine());autoGenerator.execute();}
}
此“步骤2”代码放到任意位置运行即可。
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
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.builder.ConfigBuilder;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.FileType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;// 演示例子&#xff0c;执行 main 方法控制台输入模块表名回车自动生成对应项目目录中
public class CodeGenerator {public static void main(String[] args) {// 代码生成器AutoGenerator mpg &#61; new AutoGenerator();// 全局配置GlobalConfig gc &#61; new GlobalConfig();String projectPath &#61; System.getProperty("user.dir");gc.setOutputDir(projectPath &#43; "/src/main/java");gc.setAuthor("xxx"); gc.setOpen(false);/* 自定义文件命名&#xff0c;注意 %s 会自动填充表实体属性&#xff01; */gc.setMapperName("%sMapper");// gc.setXmlName("%sDao");gc.setServiceName("%sService");gc.setServiceImplName("%sServiceImpl");gc.setControllerName("%sController");// gc.setSwagger2(true); 实体属性 Swagger2 注解mpg.setGlobalConfig(gc);// 数据源配置DataSourceConfig dsc &#61; new DataSourceConfig();dsc.setUrl("xxx");// dsc.setSchemaName("public");dsc.setDriverName("com.mysql.cj.jdbc.Driver");dsc.setUsername("xxx"); dsc.setPassword("xxx"); mpg.setDataSource(dsc);// 包配置PackageConfig pc &#61; new PackageConfig();// pc.setModuleName(scanner("模块名"));pc.setParent("xxx"); mpg.setPackageInfo(pc);// 自定义配置InjectionConfig cfg &#61; new InjectionConfig() {&#64;Overridepublic void initMap() {// to do nothing}};// 输出resources/mapper// 如果模板引擎是 freemarkerString templatePath &#61; "/templates/mapper.xml.ftl";// 如果模板引擎是 velocity// String templatePath &#61; "/templates/mapper.xml.vm";// 自定义输出配置List
}
MyBatis-Plus代码生成器 - 掘金
MyBatisPlus 3.x 代码生成器 - 简书
Mybatis Plus————代码生成器_燃烧的小宇宙-CSDN博客
自定义模板
自定义代码生成器模板 - MyBatis Plus 教程
MybatisPlus自定义模版中能获取到的信息_开发者的博客-CSDN博客