AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。
MyBatis-Plus 从 3.0.3 之后移除了代码生成器与模板引擎的默认依赖,需要手动添加相关依赖:
<!-- mybatis代码生成器 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.0</version>
</dependency>
<!-- mybatis核心代码 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-core</artifactId>
<version>3.4.0</version>
</dependency>
<!-- 数据库连接 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<!-- 自定义模版引擎 -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.30</version>
</dependency>
<!-- java模版引擎 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
maven仓库内搜索mybatis-plus-generator,打开,复制其中的templates目录至resources
由于我们后续使用的是FreemarkerTemplateEngine,仅用到.ftl文件,其他后缀文件可自行删除。
controller.java.ftl
package ${package.Controller};
import ${package.Entity}.${entity};
import ${package.Service}.${table.serviceName};
import com.自己的工具包.RetJson;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
<#if restControllerStyle>
<#else>
import org.springframework.stereotype.Controller;
</#if>
<#if superControllerClassPackage??>
import ${superControllerClassPackage};
</#if>
import javax.validation.Valid;
import java.util.List;
/**
*
* ${table.comment} 前端控制器
*
*
* @author ${author}
* @since ${date}
*/
@Api(tags = "${table.comment}")
<#if restControllerStyle>
@RestController
<#else>
@Controller
</#if>
@RequestMapping("<#if package.ModuleName??>/${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>
@Autowired
private ${table.serviceName} ${table.serviceName?uncap_first};
@ApiOperation(value = "${table.comment}分页列表", response = ${entity}.class)
@ApiImplicitParams({
@ApiImplicitParam(name = "page", value = "页面", dataType = "Long"),
@ApiImplicitParam(name = "size", value = "页面数据量", dataType = "Long"),
@ApiImplicitParam(name = "sort", value = "排序方式排序[true:正序; false:倒序]", dataType = "Boolean"),
@ApiImplicitParam(name = "sortName", value = "排序字段,参照返回字段", dataType = "String")})
@PostMapping(value = "/page")
public Object list(@Valid @RequestBody ${entity} param) {
Object data = ${table.serviceName?uncap_first}.page(param);
return RetJson.ok(data);
}
@ApiOperation(value = "${table.comment}详情", response = ${entity}.class)
@GetMapping(value = "/info/{id}")
public Object info(@PathVariable Long id) {
Object data = ${table.serviceName?uncap_first}.info(id);
return RetJson.ok(data);
}
@ApiOperation(value = "${table.comment}新增")
@PostMapping(value = "/add")
public Object add(@Valid @RequestBody ${entity} param) {
${table.serviceName?uncap_first}.add(param);
return RetJson.ok();
}
@ApiOperation(value = "${table.comment}修改")
@PostMapping(value = "/modify")
public Object modify(@Valid @RequestBody ${entity} param) {
${table.serviceName?uncap_first}.modify(param);
return RetJson.ok();
}
@ApiOperation(value = "${table.comment}删除(单个条目)")
@GetMapping(value = "/remove/{id}")
public Object remove(@PathVariable Long id) {
${table.serviceName?uncap_first}.remove(id);
return RetJson.ok();
}
@ApiOperation(value = "${table.comment}删除(多个条目)")
@PostMapping(value = "/removes")
public Object removes(@Valid @RequestBody List<Long> ids) {
${table.serviceName?uncap_first}.removes(ids);
return RetJson.ok();
}
}
</#if>
service.java.ftl
package ${package.Service};
import ${package.Entity}.${entity};
import ${superServiceClassPackage};
import com.baomidou.mybatisplus.core.metadata.IPage;
import java.util.List;
/**
*
* ${table.comment!} 服务类
*
*
* @author ${author}
* @since ${date}
*/
<#if kotlin>
interface ${table.serviceName} : ${superServiceClass}<${entity}>
<#else>
public interface ${table.serviceName} extends ${superServiceClass}<${entity}> {
/**
* ${table.comment!}分页列表
* @param param 根据需要进行传值
* @return
*/
IPage<${entity}> page(${entity} param);
/**
* ${table.comment!}详情
* @param id
* @return
*/
${entity} info(Long id);
/**
* ${table.comment!}新增
* @param param 根据需要进行传值
* @return
*/
void add(${entity} param);
/**
* ${table.comment!}修改
* @param param 根据需要进行传值
* @return
*/
void modify(${entity} param);
/**
* ${table.comment!}删除(单个条目)
* @param id
* @return
*/
void remove(Long id);
/**
* 删除(多个条目)
* @param ids
* @return
*/
void removes(List<Long> ids);
}
</#if>
serviceImpl.java.ftl
package ${package.ServiceImpl};
import ${package.Entity}.${entity};
import ${package.Mapper}.${table.mapperName};
import ${package.Service}.${table.serviceName};
import ${superServiceImplClassPackage};
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.自己的工具包.RetJson;
import com.自己的工具包.RetCode;
import com.自己的工具包.PageUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.List;
/**
*
* ${table.comment!} 服务实现类
*
*
* @author ${author}
* @since ${date}
*/
@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} {
@Autowired
private PageUtils pageUtils;
/**
* ${table.comment!}分页列表
* @param param 根据需要进行传值
* @return
*/
@Override
public IPage<${entity}> page(${entity} param) {
QueryWrapper<${entity}> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda()
<#list table.fields as field>
// ${field.comment}
<#if !entityLombokModel>
<#if field.propertyType == "Boolean">
<#assign getprefix="is"/>
<#else>
<#assign getprefix="get"/>
</#if>
<#if field.propertyType == "String">
.eq(!StringUtils.isEmpty(param.${getprefix}${field.capitalName}()), ${entity}::${getprefix}${field.capitalName}, param.${getprefix}${field.capitalName}())
<#else>
.eq(param.${getprefix}${field.capitalName}() != null, ${entity}::${getprefix}${field.capitalName}, param.${getprefix}${field.capitalName}())
</#if>
<#else>
<#if field.propertyType == "String">
.eq(!StringUtils.isEmpty(param.get${field.capitalName}()), ${entity}::get${field.capitalName}, param.get${field.capitalName}())
<#else>
.eq(param.get${field.capitalName}() != null, ${entity}::get${field.capitalName}, param.get${field.capitalName}())
</#if>
</#if>
</#list>;
IPage<${entity}> page = page(pageUtils.page(), queryWrapper);
return page;
}
/**
* ${table.comment!}详情
* @param id
* @return
*/
@Override
public ${entity} info(Long id) {
return getById(id);
}
/**
* ${table.comment!}新增
* @param param 根据需要进行传值
* @return
*/
@Override
public void add(${entity} param) {
save(param);
}
/**
* ${table.comment!}修改
* @param param 根据需要进行传值
* @return
*/
@Override
public void modify(${entity} param) {
updateById(param);
}
/**
* ${table.comment!}删除(单个条目)
* @param id
* @return
*/
@Override
public void remove(Long id) {
removeById(id);
}
/**
* ${table.comment!}删除(多个条目)
* @param ids
* @return
*/
@Override
public void removes(List<Long> ids) {
removeByIds(ids);
}
}
</#if>
CoderGenerator.java,继承自AutoGenerator
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.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.FileType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class CoderGenerator extends AutoGenerator {
private CoderGenerator() {}
public static CoderGenerator.CoderGeneratorBuilder builder(CoderGeneratorPathVO coderGeneratorPathVO) {
return new CoderGenerator.CoderGeneratorBuilder(coderGeneratorPathVO);
}
public static class CoderGeneratorBuilder {
private DataSourceConfig dataSourceConfig;
private PackageConfig packageConfig;
private GlobalConfig globalConfig;
private InjectionConfig injectionConfig;
private StrategyConfig strategyConfig;
// private List fileOutConfigList;
// 定义不可修改的常量
// 各层包名
private static final String ENTITY_PATH = "/entity/";
private static final String MAPPER_PATH = "/mapper/";
private static final String XML_PATH = "/resources/mapper/";
private static final String SERVICE_PATH = "/service/";
private static final String SERVICE_IMPL_PATH = "/service/impl/";
private static final String CONTROLLER_PATH = "/controller/";
// 各层模版
private static final String ENTITY_TEMPLATE = "templates/entity.java.ftl";
private static final String XML_TEMPLATE = "templates/mapper.xml.ftl";
private static final String MAPPER_TEMPLATE = "templates/mapper.java.ftl";
private static final String SERVICE_TEMPLATE = "templates/service.java.ftl";
private static final String SERVICE_IMPL_TEMPLATE = "templates/serviceImpl.java.ftl";
private static final String CONTROLLER_TEMPLATE = "templates/controller.java.ftl";
// 由用户动态设置
// 各层文件输出到模块, 没有则置空
private String projectPath;
/** Entity.java, Mapper.java, Mapper.xml输出模块路径 */
private String entityOutputPath;
/** Entity.java, Mapper.java, Mapper.xml输出模块路径 */
private String mapperOutputPath;
/** Entity.java, Mapper.java, Mapper.xml输出模块路径 */
private String daoOutputPath;
/** mapper.xml输出模块路径(需要注意放置的位置:默认从模块/src/main下开始) */
private String xmlOutputPath;
/** IService.java, serviceImpl.java输出模块路径 */
private String serviceOutputPath;
/** Controller.java输出模块路径 */
private String controllerOutputPath;
private CoderGeneratorBuilder(CoderGeneratorPathVO coderGeneratorPathVO) {
this.projectPath = coderGeneratorPathVO.getProjectPath();
this.entityOutputPath = coderGeneratorPathVO.getEntityOutputPath();
this.mapperOutputPath = coderGeneratorPathVO.getMapperOutputPath();
this.daoOutputPath = coderGeneratorPathVO.getDaoOutputPath();
this.xmlOutputPath = coderGeneratorPathVO.getXmlOutputPath();
this.serviceOutputPath = coderGeneratorPathVO.getServiceOutputPath();
this.controllerOutputPath = coderGeneratorPathVO.getControllerOutputPath();
this.injectionConfig = injectionConfig();
// this.fileOutConfigList = this.fileOutConfigList();
}
public static CoderGenerator.CoderGeneratorBuilder builder(CoderGeneratorPathVO coderGeneratorPathVO) {
return new CoderGenerator.CoderGeneratorBuilder(coderGeneratorPathVO);
}
public CoderGenerator.CoderGeneratorBuilder dataSourceConfig(String jdbcUrl, String driverName, String username, String password) {
dataSourceConfig = new DataSourceConfig();
dataSourceConfig.setUrl(jdbcUrl);
dataSourceConfig.setDriverName(driverName);
dataSourceConfig.setUsername(username);
dataSourceConfig.setPassword(password);
return this;
}
public CoderGenerator.CoderGeneratorBuilder packageConfig(String parent) {
String entity = ENTITY_PATH;
String mapper = MAPPER_PATH;
String xml = XML_PATH;
String service = SERVICE_PATH;
String serviceImpl = SERVICE_IMPL_PATH;
String controller = CONTROLLER_PATH;
packageConfig = new PackageConfig()
// 父包名
.setParent(parent.replace('/', '.').substring(1))
.setEntity(entity.replace('/', '.').substring(1, entity.length()-1))
.setMapper(mapper.replace('/', '.').substring(1, mapper.length()-1))
.setXml(xml.replace('/', '.').substring(1, xml.length()-1))
.setService(service.replace('/', '.').substring(1, service.length()-1))
.setServiceImpl(serviceImpl.replace('/', '.').substring(1, serviceImpl.length()-1))
.setController(controller.replace('/', '.').substring(1, controller.length()-1));
return this;
}
/**
* 策略配置
*/
public CoderGenerator.CoderGeneratorBuilder strategyConfig(CoderGeneratorTableVO coderGeneratorTableVO) {
this.strategyConfig = new StrategyConfig()
// 表名生成策略:下划线连转驼峰
.setNaming(NamingStrategy.underline_to_camel)
// 表字段生成策略:下划线连转驼峰
.setColumnNaming(NamingStrategy.underline_to_camel)
// 需要生成的表
.setInclude(coderGeneratorTableVO.getTableName())
// 生成controller
.setRestControllerStyle(true)
// 去除表前缀
.setTablePrefix(coderGeneratorTableVO.getEntityPrefix())
// controller映射地址:驼峰转连字符
.setControllerMappingHyphenStyle(true)
// 是否启用builder 模式
.setEntityBuilderModel(true)
// 是否为lombok模型; 需要lombok依赖
.setEntityLombokModel(true)
// 生成实体类字段注解
.setEntityTableFieldAnnotationEnable(true);
return this;
}
/**
* 全局配置
*/
public CoderGenerator.CoderGeneratorBuilder globalConfig(String author) {
this.globalConfig = new GlobalConfig()
// 打开文件
.setOpen(false)
// 文件覆盖
.setFileOverride(true)
// 开启activeRecord模式
.setActiveRecord(true)
// XML ResultMap: mapper.xml生成查询映射结果
.setBaseResultMap(true)
// XML ColumnList: mapper.xml生成查询结果列
.setBaseColumnList(true)
// swagger注解; 须添加swagger依赖
.setSwagger2(true)
// 作者
.setAuthor(author);
return this;
}
public CoderGenerator build() {
CoderGenerator coderGenerator = new CoderGenerator();
// 置空模版
coderGenerator.setTemplate(templateConfig());
if (dataSourceConfig != null) {
coderGenerator.setDataSource(dataSourceConfig);
}
if (packageConfig != null) {
coderGenerator.setPackageInfo(packageConfig);
}
if (globalConfig != null) {
coderGenerator.setGlobalConfig(globalConfig);
}
if (strategyConfig != null) {
coderGenerator.setStrategy(strategyConfig);
}
coderGenerator.setCfg(injectionConfig);
return coderGenerator;
}
/**
* 模板配置
*/
private TemplateConfig templateConfig() {
return new TemplateConfig()
// 置空后方便使用自定义输出位置
.setEntity(null)
.setXml(null)
.setMapper(null)
.setService(null)
.setServiceImpl(null)
.setController(null);
}
/**
* 自定义配置
*/
private InjectionConfig injectionConfig() {
return new InjectionConfig() {
@Override
public void initMap() {
// 注入配置
}
}
// 判断是否创建文件
.setFileCreate(new IFileCreate() {
@Override
public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
// 检查文件目录,不存在自动递归创建
checkDir(filePath);
// 指定需要覆盖的文件
// 文件结尾名字参照 全局配置 中对各层文件的命名,未修改为默认值
if (isExists(filePath) && (!filePath.endsWith("Mapper.xml") && !filePath.endsWith("Dao.java") && !filePath.endsWith("Mapper.java"))) {
return false;
}
return true;
}
})
// 自定义输出文件
.setFileOutConfigList(fileOutConfigList());
}
/**
* 自定义输出文件配置
*/
private List<FileOutConfig> fileOutConfigList() {
List<FileOutConfig> list = new ArrayList<>();
// 实体类文件输出
list.add(new FileOutConfig(ENTITY_TEMPLATE) {
@Override
public String outputFile(TableInfo tableInfo) {
return entityOutputPath + tableInfo.getEntityName() + StringPool.DOT_JAVA;
}
});
// mapper xml文件输出
list.add(new FileOutConfig(XML_TEMPLATE) {
@Override
public String outputFile(TableInfo tableInfo) {
return xmlOutputPath + tableInfo.getMapperName() + StringPool.DOT_XML;
}
});
// mapper文件输出
list.add(new FileOutConfig(MAPPER_TEMPLATE) {
@Override
public String outputFile(TableInfo tableInfo) {
return mapperOutputPath + tableInfo.getMapperName() + StringPool.DOT_JAVA;
}
});
// service文件输出
list.add(new FileOutConfig(SERVICE_TEMPLATE) {
@Override
public String outputFile(TableInfo tableInfo) {
return serviceOutputPath + tableInfo.getServiceName() + StringPool.DOT_JAVA;
}
});
// service impl文件输出
list.add(new FileOutConfig(SERVICE_IMPL_TEMPLATE) {
@Override
public String outputFile(TableInfo tableInfo) {
return serviceOutputPath + tableInfo.getServiceImplName() + StringPool.DOT_JAVA;
}
});
// controller文件输出
list.add(new FileOutConfig(CONTROLLER_TEMPLATE) {
@Override
public String outputFile(TableInfo tableInfo) {
return controllerOutputPath + tableInfo.getControllerName() + StringPool.DOT_JAVA;
}
});
return list;
}
/**
* 判断文件是否存在
* @param path 路径
* @return
*/
private static boolean isExists(String path) {
File file = new File(path);
return file.exists();
}
}
}
CoderGeneratorPathVO.java
@Data
import lombok.Data;
@Data
public class CoderGeneratorPathVO {
@ApiModelProperty("项目根路径")
private String projectPath;
@ApiModelProperty("实体类输出路径")
private String entityOutputPath;
@ApiModelProperty("mapper层输出路径")
private String mapperOutputPath;
@ApiModelProperty("dao层输出路径")
private String daoOutputPath;
@ApiModelProperty("xml输出路径")
private String xmlOutputPath;
@ApiModelProperty("服务层输出路径")
private String serviceOutputPath;
@ApiModelProperty("控制层输出路径")
private String controllerOutputPath;
}
CoderGeneratorTableVO.java
import lombok.Data;
@Data
public class CoderGeneratorTableVO {
private String tableName;
private String entityPrefix;
public CoderGeneratorTableVO(String tableName, String entityPrefix) {
this.tableName = tableName;
this.entityPrefix = entityPrefix;
}
}
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
public class MySqlGenerator {
public static void main(String[] args) {
// 代码生成器
String jdbcUrl = "jdbcURL";
String username = "root";
String password = "password";
CoderGeneratorPathVO coderGeneratorPathVO = new CoderGeneratorPathVO();
coderGeneratorPathVO.setControllerOutputPath("controller绝对路径");
coderGeneratorPathVO.setDaoOutputPath("dao绝对路径");
coderGeneratorPathVO.setEntityOutputPath("entity绝对路径");
coderGeneratorPathVO.setMapperOutputPath("mapper绝对路径");
coderGeneratorPathVO.setProjectPath("项目绝对路径");
coderGeneratorPathVO.setServiceOutputPath("service绝对路径");
coderGeneratorPathVO.setXmlOutputPath("xml绝对路径");
CoderGenerator mpg = CoderGenerator.builder(coderGeneratorPathVO)
.dataSourceConfig(jdbcUrl, "com.mysql.jdbc.Driver", username, password)
.strategyConfig(new CoderGeneratorTableVO("sys_user", ""))
.globalConfig("author")
.packageConfig("包名")
.build();
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();
}
}