Mybatis-plus-Generator 3.5.5 自定义模板支持 (DTO/VO 等) 配置

news2024/11/15 19:23:57

随着项目节奏越来越快,为了减少把时间浪费在新建DTO 、VO 等地方,直接直接基于Mybatis-plus 这颗大树稍微扩展一下,在原来生成PO、 DAO、Service、ServiceImpl、Controller 基础新增。为了解决这个问题,网上找了一堆资料,发现都是老版本的,都是基于老的AutoGenerator ,里面配置非常臃肿,基于FastAutoGenerator 链式实现没有,通过Mybatis-Plus官方文档发现两个核心配置注入配置 (InjectionConfig),下面是官方文档解释

上面是官方文档的案例,存在两个问题,一个并没有other这个属性,第二个框生成的DTO实体会在系统parent目录下。本着要弄就要完美的执着,通过一下午翻阅mybatis-plus-generator 的源码,终于找到定位输出目录类配置CustomFile。下面直接上代码

POM依赖:

  <!--gen code start-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.5</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.33</version>
        </dependency>
        <!--gen code ebd-->

构建代码:

 FastAutoGenerator.create("jdbc:mysql://xxxx:63306/diboot",
                        "diboot", "xxx")
                //全局配置
                .globalConfig(builder -> {
                    builder.outputDir(Paths.get(System.getProperty("user.dir")) + "/src/main/java")
                            .author("xxx")
                            .build();
                })
                //包配置
                .packageConfig(builder -> {
                    builder.parent("com.example.demo")
                            .entity("model.po")
                            .service("biz")
                            .serviceImpl("biz")
                            .mapper("dao")
                           // .xml("dao.xml")
                            .controller("api.back")
                            .build();
                })
                //表策略配置
                .strategyConfig(builder -> {
                    builder.enableSkipView()
                            .disableSqlFilter()
                            .addTablePrefix("biz_", "sys_")
                            .addInclude("biz_article")
                            .build();
                })
                //entity策略
                .strategyConfig(builder -> {
                    builder.entityBuilder().idType(IdType.ASSIGN_ID)
                            .superClass(BaseModel.class)
                            .disableSerialVersionUID()
                            .enableRemoveIsPrefix()
                            .enableLombok()
                            .addIgnoreColumns("is_deleted", "create_time", "update_time")
                            .build();
                })
                //controller 策略
                .strategyConfig(builder -> {
                    builder.controllerBuilder()
                            .enableHyphenStyle()
                            .enableRestStyle()
                            .formatFileName("%sController")
                            .build();
                })
                //Service 策略
                .strategyConfig(builder -> {
                    builder.serviceBuilder()
                            .superServiceClass(IService.class)
                            .superServiceImplClass(ServiceImpl.class)
                            .formatServiceFileName("%sService")
                            .formatServiceImplFileName("%sServiceImpl")
                            .build();
                })
                //mapper 策略
                .strategyConfig(builder -> {
                    builder.mapperBuilder()
                            .superClass(BaseMapper.class)
                            .mapperAnnotation(Repository.class)
                            .enableBaseResultMap()
                            .enableBaseColumnList()
                            .formatMapperFileName("%sMapper")
                            .build();
                })
                //注入自定义配置
                .injectionConfig(builder -> {
                    /**自定义生成模板参数,在ftl模版里取值使用**/
                    Map<String,Object> data = new HashMap<>();
                    data.put("entityBuilderModel", true);
                    data.put("chainModel", true);
                    data.put("swagger",true);
                    data.put("entitySerialVersionUID",true);
                    data.put("entityLombokModel", true);
                    builder.customMap(data);
                    List<CustomFile> customFiles = new ArrayList();
                    /**DTO实体**/
                    CustomFile updateInputFile = new CustomFile.Builder()
                            .fileName("UpdateInput.java")//生成java文件名称,要和ftl模版里的文件名保持一致
                            .templatePath("/templates/UpdateInput.java.ftl")//实体模板位置
                            .packageName("model.dto")//生成文件包名
                            .build();
                    customFiles.add(updateInputFile);
                    CustomFile addInputFile = new CustomFile.Builder()
                            .fileName("AddInput.java")
                            .templatePath("/templates/AddInput.java.ftl")
                            .packageName("model.dto").build();
                    /**Vo实体**/
                    CustomFile customFileVO = new CustomFile.Builder()
                            .fileName("VO.java")
                            .templatePath("/templates/VO.java.ftl")
                            .packageName("model.vo").build();
                    customFiles.add(customFileVO);

                    customFiles.add(addInputFile);
                    builder.customFile(customFiles);
                })
                .templateEngine(new FreemarkerTemplateEngine())
                .execute();

DTO ftl模版,为了测地解决不需要修改生成实体,根据数据库字段注释生成实体字段注释,根据数据库字段是否允许为空 加上NotBlank 或者 NotNull  以及 @ApiModelProperty 的required 的条件

新增DTO模版代码,已经调试过输出美化内容,有需要的可以直接复制

package ${package.Parent}.model.dto;
<#if swagger>
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
</#if>
<#if entityLombokModel>
import lombok.Getter;
import lombok.Setter;
    <#if chainModel>
import lombok.experimental.Accessors;
    </#if>
</#if>
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.io.Serializable;
import java.io.Serial;
import java.time.*;
/**
* <p>
    * ${table.comment!}
    * </p>
*
* @author ${author}
* @since ${date}
*/
<#if entityLombokModel>
@Getter
@Setter
    <#if chainModel>
@Accessors(chain = true)
    </#if>
</#if>
<#if swagger>@ApiModel(description = "${table.comment!}")
</#if>
public class ${entity}AddInput implements Serializable {
<#if entitySerialVersionUID>
    @Serial
    private static final long serialVersionUID = 1L;
</#if>
<#-- ----------  BEGIN 字段循环遍历  ---------->
<#list table.fields as field>
    <#if !field.keyFlag && field.propertyName!="tenantId"&&field.propertyName!="museumId"><#--不是主键、不是租户ID 输出-->
    <#if field.comment!?length gt 0>
        <#if field.metaInfo.nullable>

     @ApiModelProperty(value="${field.comment}")
        <#else>

     @ApiModelProperty(value="${field.comment}",required = true)
            <#if field.propertyType=="string">
     @NotBlank(message = "${field.comment}不能为空")
            <#else>
     @NotNull(message = "${field.comment}不能为空")
            </#if>
        </#if>
    </#if>
     private ${field.propertyType} ${field.propertyName};
    </#if>
</#list>
<#------------  END 字段循环遍历  ---------->
}

生成效果图:自动加上参数校验

修改DTO模版代码
 

package ${package.Parent}.model.dto;
<#if swagger>
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
</#if>
<#if entityLombokModel>
import lombok.Getter;
import lombok.Setter;
    <#if chainModel>
import lombok.experimental.Accessors;
    </#if>
</#if>
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.io.Serializable;
import java.io.Serial;
import java.time.*;
/**
* <p>
    * ${table.comment!}
    * </p>
*
* @author ${author}
* @since ${date}
*/
<#if entityLombokModel>
@Getter
@Setter
    <#if chainModel>
@Accessors(chain = true)
    </#if>
</#if>
<#if swagger>@ApiModel(description = "${table.comment!}")
</#if>
public class ${entity}UpdateInput implements Serializable {
<#if entitySerialVersionUID>
    @Serial
    private static final long serialVersionUID = 1L;
</#if>
<#-- ----------  BEGIN 字段循环遍历  ---------->
<#list table.fields as field>
    <#if field.propertyName!="tenantId"&&field.propertyName!="museumId"><#--不是租户ID 输出-->
    <#if field.comment!?length gt 0>
        <#if field.metaInfo.nullable>

     @ApiModelProperty(value="${field.comment}")
        <#else>

     @ApiModelProperty(value="${field.comment}",required = true)
            <#if field.propertyType=="string">
     @NotBlank(message = "${field.comment}不能为空")
            <#else>
     @NotNull(message = "${field.comment}不能为空")
            </#if>
        </#if>
    </#if>
     private ${field.propertyType} ${field.propertyName};
    </#if>
</#list>
<#------------  END 字段循环遍历  ---------->
}

生成效果图:

VO模版:

package ${package.Parent}.model.vo;
<#if swagger>
    import io.swagger.annotations.ApiModel;
    import io.swagger.annotations.ApiModelProperty;
</#if>
<#if entityLombokModel>
    import lombok.Getter;
    import lombok.Setter;
    <#if chainModel>
        import lombok.experimental.Accessors;
    </#if>
</#if>
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.io.Serializable;
import java.io.Serial;
import java.time.*;
/**
* <p>
    * ${table.comment!}
    * </p>
*
* @author ${author}
* @since ${date}
*/
<#if entityLombokModel>
@Getter
@Setter
    <#if chainModel>
@Accessors(chain = true)
    </#if>
</#if>
<#if swagger>@ApiModel(description = "${table.comment!}")
</#if>
public class ${entity}VO implements Serializable {
<#if entitySerialVersionUID>
    @Serial
    private static final long serialVersionUID = 1L;
</#if>
<#-- ----------  BEGIN 字段循环遍历  ---------->
<#list table.fields as field>
    <#if field.propertyName!="tenantId"&&field.propertyName!="museumId"><#--不是租户ID 输出-->
        <#if field.comment!?length gt 0>

        @ApiModelProperty(value="${field.comment}")
        </#if>
        private ${field.propertyType} ${field.propertyName};
    </#if>
</#list>
<#------------  END 字段循环遍历  ---------->
}

效果图:

项目结构截图:

能看到这里应该有个大概的了解了,既然能生成自定义DTO 和 VO,那我们完全也可以覆盖之前的默认Service,将生成好的 DTO 和VO 放入 Service 模版里,然后将Service模版里 放入Controller模版里,那我们一次性就可以把 PO VO DTO 以及 Service 里增删改查 全部实现,并放到 Controller接口 ,那常用的业务基本上就可以使用了,接口上加上一些权限 注解和日志注解。如果有些特殊的逻辑再生成的service调整即可。后续有时间,把Service的模版也出一个教程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2137931.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【硬件模块】SHT20温湿度传感器

SHT20是一个用IIC通信的温湿度传感器。我们知道这个就可以了。 它支持的电压范围是2.1~3.6V&#xff0c;推荐是3V&#xff0c;所以如果我们的MCU是5V的&#xff0c;那么就得转个电压才能用了。 IIC常见的速率有100k&#xff0c;400k&#xff0c;而SHT20是支持400k的&#xff08…

Parallels Desktop 20破解版(Mac虚拟机) v20.0.0 for Mac 最新商业版(支持M系列)

Parallels Desktop 20是一款目前功能最强大灵活度最高的虚拟机软件&#xff0c;可运行数千种 Windows 应用程序&#xff0c;如 Microsoft Office、Internet Explorer、Access、Quicken、QuickBooks、Visual Studio&#xff0c;甚至支持对图像要求较高的游戏和 CAD 项目&#xf…

[产品管理-17]:NPDP新产品开发 - 15 - 产品设计与开发工具 - 工欲善其事,必先利其器 - 创意工具:借助各种工具和方法,完成产品的创意

目录 前言&#xff1a; 一、创意&#xff08;用户问题 -》产品想法&#xff09;的生成 1.1 创意 1.2 先发散后收敛 1.3 创意工具集 二、创意工具概述 2.1 SCAMPER - 按照数据处理逻辑运算的方式发散 SCAMPER创意工具详解&#xff1a;对数据/产品的各种运算、变换&…

如何用SQL Server和Oracle进行数据同步?

数据同步是大数据应用中非常重要的环节&#xff0c;它可以保证数据的实时性和一致性&#xff0c;为数据分析和决策提供重要依据。常见的数据同步方式包括ETL实时同步和实时ETL工具&#xff0c;其中实时ETL工具又可以分为基于日志追踪和基于触发器两种。 针对不同的数据库系统&…

Hqst 品牌 H81801D 千兆 DIP 网络变压器在光猫收发器机顶盒中的应用

Hqst 牌 H81801D 千兆 DIP 网络变压器在光猫收发器机顶盒中的应用主要包括以下几个方面&#xff1a; 1. 信号匹配和转换&#xff1a; H81801D 网络变压器能够匹配光猫收发器与以太网电缆之间的阻抗差&#xff0c;确保信号在传输过程中的完整性&#xff0c;同时它还能将光信号转…

量化交易backtrader实践(一)_数据获取篇(3)_爬取数据

这一节实践其实是在上一节之前进行的&#xff0c;背景原因是因为tushare.pro的积分不够高&#xff0c;当时还没有接触到使用akshare等其他接口&#xff0c;因此对于全股票列表用的是去网页上爬的方式获得的&#xff0c;也就借此机会&#xff0c;再复习了一遍爬虫的相关知识。 …

WPS生成目录

导航窗格&#xff1a;视图->导航窗格 可修改标题的样式&#xff0c;之后的标题直接套用即可 修改其他标题样式也是这样 添加编号&#xff1a;可以选上面的模版 也可自定义编号 生成目录&#xff1a;引用->目录->选用一个 但是我想把目录插到另一页 当我添加几个标题…

IDEA-调用Restful接口

告别Swagger3/Apifox/Postman Swagger3&#xff08;丝袜哥&#xff09; 地址&#xff1a;REST API Documentation Tool | Swagger UI简介&#xff1a;在java代码里面增加注解生成接口文档 在代码里面增加注解 RestController RequestMapping("api/v1/user") Api(ta…

移动UI案例:工具类app整套案例

工具类App是指提供各种实用工具和功能的手机应用程序。这些工具可以包括但不限于日历、闹钟、备忘录、翻译、计算器、单位转换、天气预报、地图导航、音乐播放器、相机、视频编辑等。这些工具类App能够帮助用户解决日常生活和工作中的各种问题&#xff0c;提高效率和便利性。 …

浅谈Spring Cloud:认识微服务

SpringCloud就是分布式微服务架构的一站式解决方案&#xff0c;是微服务架构落地的多种技术的集合。 目录 微服务远程调用 Eureka注册中心 搭建Eureka Server 注册组件 服务拉取 当各种各样的服务越来越多&#xff0c;拆分的也越来越细&#xff0c;此时就会出现一个服务集…

Ubuntu 22.04.5 LTS 发布下载 - 现代化的企业与开源 Linux

Ubuntu 22.04.5 LTS (Jammy Jellyfish) - 现代化的企业与开源 Linux Ubuntu 22.04.5 发布&#xff0c;配备 Linux 内核 6.8 请访问原文链接&#xff1a;https://sysin.org/blog/ubuntu-2204/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xf…

Spring Boot与gRPC的完美融合:构建高效用户服务与订单服务通信

gRPC 是一种由 Google 开发的高性能、开源的远程过程调用&#xff08;Remote Procedure Call, RPC&#xff09;框架。它允许在不同的计算机系统或进程之间进行通信&#xff0c;使得分布式系统和微服务架构中的服务之间能够轻松地相互调用方法。gRPC 基于 HTTP/2 协议&#xff0…

21章 规则集和映射

1.同20章 线性表、栈、队列和优先队列的第10题。 2.同20章 线性表、栈、队列和优先队列的第1题。 3.修改程序清单21-7中的程序。如果关键字在注释或者字符串中&#xff0c;则不进行统计。将Java文件名从命令行传递。 import java.io.*; import java.util.Arrays; import jav…

轨道列车舱门检测系统源码分享

轨道列车舱门检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer…

【Android 13源码分析】WindowContainer窗口层级-3-实例分析

在安卓源码的设计中&#xff0c;将将屏幕分为了37层&#xff0c;不同的窗口将在不同的层级中显示。 对这一块的概念以及相关源码做了详细分析&#xff0c;整理出以下几篇。 【Android 13源码分析】WindowContainer窗口层级-1-初识窗口层级树 【Android 13源码分析】WindowCon…

Redis的AOF持久化、重写机制、RDB持久化、混合持久化

1、AOF持久化 1.1.AOF持久化大致过程 概括&#xff1a;命令追加&#xff08;append&#xff09;、文件写入、文件同步&#xff08;sync&#xff09; Redis 每执行一条写操作命令&#xff0c;就把该命令以追加的方式写入到一个文件里&#xff0c;然后重启 Redis 的时候&#…

Pytest配置文件pytest.ini如何编写生成日志文件?

1、新建pytest.ini文件 [pytest] log_clitrue log_leveLNOTSET log_format %(asctime)s %(levelname)s %(message)s %(filename)s %(funcName)s %(lineno)d log_date_format %Y-%m-%d %H:%M:%Slog_file ./logdata/log.log log_file_level info log_file_format %(asctime…

实时(按帧)处理的低通滤波C语言实现

写在前面&#xff1a; 低通滤波采用一般的FIR滤波器&#xff0c;因为本次任务&#xff0c;允许的延迟较多&#xff0c;或者说前面损失的信号可以较多&#xff0c;因此&#xff0c;涉及一个很高阶的FIR滤波器&#xff0c;信号起始段的信号点可以不处理&#xff0c;以及&#xf…

召回01 基于物品是协同过滤 ItemCF

相似度&#xff0c;类似机器学习里面常用的cosine相似度

python AssertionError: Torch not compiled with CUDA enabled

查看&#xff1a;torch import torch# 输出带CPU&#xff0c;表示torch是CPU版本的 print(ftorch的版本是&#xff1a;{torch.__version__}) # print(ftorch是否能使用cuda&#xff1a;{torch.cuda.is_available()}) 修改一下代码&#xff0c;将cuda改成cpu 最后运行正常&…