代码生成器:MyBatis-Plus代码生成自定义模版

简述

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包内的模版

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;

/**
* <p>
 * ${table.comment} 前端控制器
 * </p>
*
* @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;

/**
* <p>
 * ${table.comment!} 服务类
 * </p>
*
* @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;

/**
* <p>
 * ${table.comment!} 服务实现类
 * </p>
*
* @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>

为方便后续调用,封装了自定义模版的AutoGenerator

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<FileOutConfig> 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();
    }
}

运行结果

在这里插入图片描述

  • 6
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值