mybatis-plus AutoGenerator 自定义包 模板

1,997 阅读2分钟

mybatis-plus 的一款自动生成代码常规包就entity,mapper,service,controller,mapper.xml这几层, 如果按照常规的这样配置,官方文档就有说。 mybatis-plus官方教程

但是业务中可能会多一层manager层,这种情况怎么办呢,mybatis-plus提供了自定义的方法,可以自定义包名,但是官方文档提及太少

image.png 就这几行的带过了,导致我冥思苦想之下,网上也没找到好的教材,自己就试着用一下

依赖

<!--mybatis plus启动器-->
<dependency>
   <groupId>com.baomidou</groupId>
   <artifactId>mybatis-plus-boot-starter</artifactId>
   <version>3.5.1</version>
</dependency>
<!-- 代码生成器模板,用于生成代码 -->
<dependency>
   <groupId>org.apache.velocity</groupId>
   <artifactId>velocity-engine-core</artifactId>
   <version>2.3</version>
</dependency>

<dependency>
   <groupId>com.baomidou</groupId>
   <artifactId>mybatis-plus-generator</artifactId>
   <version>3.5.1</version>
</dependency>

<!-- freemarker模板 -->
<dependency>
   <groupId>org.freemarker</groupId>
   <artifactId>freemarker</artifactId>
   <version>2.3.30</version>
</dependency>

本项目是基于springboot来使用,其余的什么mapper包路径就不配置了,比较懒

image.png 接下来是常规配置

public class MpGeneratorUtils {
    public static void main(String[] args) {
        String[] tablesName = {"t_user_line"};
        tablesName(tablesName);
    }

    public static void tablesName(String[] tablesName){
        String projectPath = System.getProperty("user.dir");
        String packageName = "com.unittec.pic.utils.common.augenerator"; //完整包名
        String dbUrl="jdbc:mysql://xxx?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8";
        String dbDriverName="com.mysql.jdbc.Driver";
        String dbUsername="xxx";
        String dbPassword="xxx";

        FastAutoGenerator.create(dbUrl, dbUsername, dbPassword)
                .globalConfig(builder -> {
                    builder.author("liuxin") // 设置作者
                            .enableSwagger() // 开启swagger模式
                            .fileOverride() // 覆盖已生成的目录
                            .outputDir(projectPath + "/src/main/java") // 指定输出目录.
                            .disableOpenDir() // 禁止打开输出目录
                            .dateType(DateType.TIME_PACK) // 指定时间类型
                            .commentDate("yyyy-MM-dd HH:ss:mm"); // 注释日期
                })
                .packageConfig(builder -> {
                    builder.parent(packageName) // 设置父包名
                            .other("")// manager包
                            //.other("manager.impl") // manager.impl 实现类包名
                            .pathInfo(Collections.singletonMap(OutputFile.mapperXml, projectPath + "/src/main/resources/mappers")); // 设置mapperXml生成路径
                })
                .templateConfig(builder -> {
                    builder.entity("templates/entity.java")
                            .service("templates/service.java")
                            .serviceImpl("templates/serviceImpl.java")
                            .mapper("templates/mapper.java")
                            .mapperXml("templates/mapper.xml")
                            .controller("templates/controller.java");
                })
                .injectionConfig(builder -> {
                    /*Map<String,String> mapImpl1 = new HashMap();
                    mapImpl1.put("1111","11111");
                    builder.customFile(mapImpl1);*/

                    builder.beforeOutputFile((tableInfo,objMap) -> {
                        objMap.put("supperManagerClassPackage",classInfo(IManager.class)[0]);
                        objMap.put("supperManagerClassName",classInfo(IManager.class)[1]);
                        objMap.put("managerName","I" + tableInfo.getEntityName() + "Manager");
                        objMap.put("managerNameImpl",tableInfo.getEntityName() + "ManagerImpl");
                        objMap.put("superManagerImplClassName",classInfo(BaseManager.class)[1]);
                        objMap.put("superManagerImplClassPackage",classInfo(BaseManager.class)[0]);
                        objMap.put("responseInfoName",classInfo(ResponseInfo.class)[1]);
                        objMap.put("responseInfoPackage",classInfo(ResponseInfo.class)[0]);
                        objMap.put("sqlAlias","${alias}");

                        Map<String,String> mapImpl = new HashMap();
                        mapImpl.put("manager/I" + tableInfo.getEntityName() + "Manager.java","templates/manager.java.ftl");
                        mapImpl.put("manager/impl/" + tableInfo.getEntityName() + "ManagerImpl.java", "templates/managerImpl.java.ftl");
                        builder.customFile(mapImpl);
                    }); // 输出文件之前消费者

                })
                .strategyConfig(builder -> {
                    builder.addInclude(tablesName) // 设置需要生成的表名
                            .enableCapitalMode()// 开启大写命名
                            .entityBuilder() // 实体类配置
                            .enableLombok() // 开启lombok注解
                            .enableTableFieldAnnotation() // 开启生成实体时生成字段注解
                            .serviceBuilder() // service配置
                            .superServiceImplClass(BaseService.class) // service实现类的包
                            .mapperBuilder() // mapper层配置
                            .superClass(BaseMapper.class)
                            .enableMapperAnnotation()// 开启mapper注解
                            .enableBaseColumnList() //启用 BaseColumnList
                            .enableBaseResultMap() // 启用 BaseResultMap 生成
                            .controllerBuilder()
                            .superClass(BaseController.class)
                            .enableRestStyle() // 开启驼峰转连字符
                            .enableHyphenStyle(); // 开启生成@RestController 控制器
                })
                .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
                .execute();
    }
public static String[] classInfo(Class tClass){
    String[] s = new String[2];
    s[0] = tClass.getName();
    s[1] = tClass.getSimpleName();
    System.out.println(s[0] + "\n" + s[1]);
    return s;
}

这基本都是官方文档上面的操作,按着操作就行了,最关键的是自定义 断点调试

image.png 发现tableInfo与objmap中存着很多数据,这就是从数据库中读出来的数据,与自己配置的一些参数。代码生成器就是一个工厂,获取数据之后通过模板进行生产,模板在哪里呢?源码

image.png 在 AutoGenerator 中如果我们不配置模板的的话,默认使用 Velocity 引擎模板,在 templates文件目录下提供了三种模板引擎 .vm是Velocity 默认。 .ftl是 freemarker模板。 .btl 是beetl模板。本次使用freemarker模板,为了与业务代码相吻合,进行了模板的重构 serviceImpl层

package ${package.ServiceImpl};

import com.github.pagehelper.PageInfo;
import ${package.Service}.${table.serviceName};
import ${superServiceImplClassPackage};
import org.springframework.stereotype.Service;
import ${package.Entity}.${entity};
import ${package.Other}${entity}.manager.${managerName};
import org.springframework.beans.factory.annotation.Autowired;

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} implements ${table.serviceName} {

    @Autowired
    private ${managerName}  ${managerName?uncap_first};

    /***
    * @Title: add
    * @Param: [${entity?uncap_first}]
    * @description: 新增数据
    * @author: ${author}
    * @date: ${date}
    * @return: void
    * @throws:
    * @param ${entity?uncap_first}
    */
    @Override
    public void add(${entity} ${entity?uncap_first}) {
        ${managerName?uncap_first}.add(${entity?uncap_first});
    }

    /***
    * @Title: queryByPage
    * @Param: [${entity?uncap_first}, page, limit]
    * @description: 条件分页查询
    * @author: ${author}
    * @date: ${date}
    * @return: com.github.pagehelper.PageInfo<${package.Entity}.${entity}>
    * @throws:
    */
    @Override
    public PageInfo<${entity}> queryByPage(${entity} ${entity?uncap_first},Integer page, Integer limit) {
      return ${managerName?uncap_first}.queryForPage(${entity?uncap_first},page,limit);
    }

    /***
    * @Title: query
    * @Param: [${entity?uncap_first}]
    * @description: 根据实体条件查询
    * @author: ${author}
    * @date: ${date}
    * @return: java.util.List<${package.Entity}.${entity}>
    * @throws:
    * @param ${entity?uncap_first}
    */
    @Override
    public List<${entity}> query(${entity} ${entity?uncap_first}) {
      return ${managerName?uncap_first}.queryAll(${entity?uncap_first});
    }

    /***
    * @Title: queryById
    * @Param: [id]
    * @description: 通过主键查询
    * @author: ${author}
    * @date: ${date}
    * @return: ${package.Entity}.${entity}
    * @throws:
    * @param id
    */
    @Override
    public ${entity} queryById(String id) {
      return ${managerName?uncap_first}.selectById(id);
    }

    /***
    * @Title: updateById
    * @Param: [${entity?uncap_first}]
    * @description: 通过id修改参数
    * @author: ${author}
    * @date: ${date}
    * @return: void
    * @throws:
    * @param ${entity?uncap_first}
    */
    @Override
    public void updateById(${entity} ${entity?uncap_first}) {
        ${managerName?uncap_first}.updateById(${entity?uncap_first});
    }

    /***
    * @Title: updateByConditon
    * @Param: [${entity?uncap_first}, condition]
    * @description: 按条件跟新数据
    * @author: ${author}
    * @date: ${date}
    * @return: void
    * @throws:
    */
    @Override
    public void updateByConditon(${entity} ${entity?uncap_first},${entity} condition) {
        ${managerName?uncap_first}.updateByConditon(${entity?uncap_first},condition);
    }

    /***
    * @Title: deleteById
    * @Param: [id]
    * @description: 通过主键删除
    * @author: ${author}
    * @date: ${date}
    * @return: void
    * @throws:
    * @param id
    */
    @Override
    public void deleteById(String id) {
        ${managerName?uncap_first}.deleteById(id);
    }

    /***
    * @Title: deleteByIds
    * @Param: [ids]
    * @description: 批量删除
    * @author: ${author}
    * @date: ${date}
    * @return: void
    * @throws:
    * @param ids
    */
    @Override
    public void deleteByIds(String[] ids) {
        ${managerName?uncap_first}.deleteByIds(ids);
    }

}
</#if>

对于新建的manager层

package ${package.Other}${entity}.manager.impl;

import ${package.Entity}.${entity};
import ${superManagerImplClassPackage};
import ${superMapperClassPackage};
import org.springframework.stereotype.Repository;
import ${package.Other}${entity}.manager.${managerName};
import org.springframework.beans.factory.annotation.Autowired;
import ${package.Mapper}.${table.mapperName};

/**
* <p>
    * ${table.comment!} 服务实现类
    * </p>
*
* @author ${author}
* @since ${date}
*/
@Repository
public class ${managerNameImpl} extends ${superManagerImplClassName}<${entity}> implements ${managerName} {

    @Autowired
    private ${table.mapperName} ${table.mapperName?uncap_first};

    /**
    * 获取数据操作接口Mapper
    *
    * @return
    */
    @Override
    protected ${superMapperClass}<${entity}> getDao() {
        return ${table.mapperName?uncap_first};
    }

}

里面的一些配置是参数是没有的,所以我们需要手动去配置参数

.injectionConfig(builder -> {
    /*Map<String,String> mapImpl1 = new HashMap();
    mapImpl1.put("1111","11111");
    builder.customFile(mapImpl1);*/

    builder.beforeOutputFile((tableInfo,objMap) -> {
        objMap.put("supperManagerClassPackage",classInfo(IManager.class)[0]);
        objMap.put("supperManagerClassName",classInfo(IManager.class)[1]);
        objMap.put("managerName","I" + tableInfo.getEntityName() + "Manager");
        objMap.put("managerNameImpl",tableInfo.getEntityName() + "ManagerImpl");
        objMap.put("superManagerImplClassName",classInfo(BaseManager.class)[1]);
        objMap.put("superManagerImplClassPackage",classInfo(BaseManager.class)[0]);
        objMap.put("responseInfoName",classInfo(ResponseInfo.class)[1]);
        objMap.put("responseInfoPackage",classInfo(ResponseInfo.class)[0]);
        objMap.put("sqlAlias","${alias}");

        Map<String,String> mapImpl = new HashMap();
        mapImpl.put("manager/I" + tableInfo.getEntityName() + "Manager.java","templates/manager.java.ftl");
        mapImpl.put("manager/impl/" + tableInfo.getEntityName() + "ManagerImpl.java", "templates/managerImpl.java.ftl");
        builder.customFile(mapImpl);
    }); // 输出文件之前消费者

})

这一层便是自定义的一些参数配置。生成的文件路劲

image.png

image.png

请多指教!