mybatis-plus-generator 使用 velocity 生成前后台代码

news2024/11/25 16:18:06

操作步骤

        1)准备mybatis-plus 生成代码的 vm文件

        2)添加依赖 mybatis-plus-generator 代码生成器的依赖

        3)执行工具方法生成代码

1、准备 mybatis-plus 生成代码的 vm文件

1)找vm模板

去工程的 external Libraries 找到 mybatisplus-generator 下 的vm 模版

2)根据模板编写模版代码

如下图,包含所有前后台代码、菜单sql;代码结构仿照若依,基础模版来自mybatisplus-generator

提供基础的基本包含所的 :entity.java.vm ,包含数据库必字段判断的生成规则

package ${package.Entity};

import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
#foreach($pkg in $table.importPackages)
#if(!$reTool.contains("(io\.Serializable)",$pkg))
import ${pkg};
#end
#end
#if($swagger)
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
#end
import jakarta.validation.constraints.NotNull;
#if($entityLombokModel)
import lombok.Getter;
import lombok.Setter;
    #if($chainModel)
import lombok.experimental.Accessors;
    #end
#end

/**
 * <p>
 * ${table.comment}
 * </p>
 *
 * @author ${author}
 * @since ${date}
 */
#if($entityLombokModel)
@Getter
@Setter
#if($chainModel)
@Accessors(chain = true)
#end
#end
#if($table.convert)
@TableName("${schemaName}${table.name}")
#end
#if($swagger)
@ApiModel(value = "${entity}对象", description = "${table.comment}")
#end
#if($superEntityClass)
public class ${entity} extends ${superEntityClass}#if($activeRecord)${entity}#end {
#elseif($activeRecord)
public class ${entity} extends Model<${entity}> {
#elseif($entitySerialVersionUID)
public class ${entity} implements Serializable {
#else
public class ${entity} {
#end
#*#if($entitySerialVersionUID)

    private static final long serialVersionUID = 1L;
#end*#
#*-- ----------  BEGIN 字段循环遍历  ----------*#
#foreach($field in $table.fields)
    #if($tool.isNotEmpty($field.comment))
        #if($swagger)
    @ApiModelProperty("${field.comment}")
        #else
    /**
     * ${field.comment}
     */
        #end
    #end
    #if($field.keyFlag)
        #if($field.keyIdentityFlag)
    @TableId(value = "${field.annotationColumnName}", type = IdType.AUTO)
        #elseif($idType)
    @TableId(value = "${field.annotationColumnName}", type = IdType.${idType})
        #elseif($field.convert)
    @TableId("${field.annotationColumnName}")
        #end
    #elseif($field.fill)#*普通字段*#
        #if($field.convert)
    @TableField(value = "${field.annotationColumnName}", fill = FieldFill.${field.fill})#*存在数据库表字段转换*#
        #else
    @TableField(fill = FieldFill.${field.fill})
        #end
    #elseif($field.convert)
    @TableField("${field.annotationColumnName}")
    #end
    #if($field.versionField)
    @Version#*-- 乐观锁注解 --*#
    #end
    #if($field.logicDeleteField)
    @TableLogic#*-- 逻辑删除注解 --*#
    #end
    #if(!$field.keyFlag && $field.metaInfo && !$field.metaInfo.nullable)
    @NotNull(message = "${field.comment} 不应为空")#*不验证主键和二进制类型 为空*#
    #end
    #if($field.keyFlag || $field.propertyType == "byte[]")
    @ExcelIgnore#*-- 主键或二进制不导入 --*#
    #end
    @ExcelProperty("#if($field.metaInfo && !$field.metaInfo.nullable)*#end${field.comment}")
    private ${field.propertyType} ${field.propertyName};

#end
#*------------  END 字段循环遍历  ----------*#
#if(!$entityLombokModel)
#foreach($field in $table.fields)
    #if($field.propertyType == "boolean")
        #set($getprefix = "is")
    #else
        #set($getprefix = "get")
    #end
    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}) {
    #end
        this.${field.propertyName} = ${field.propertyName};
        #if($chainModel)
        return this;
        #end
    }

#end
#end
#if(!$entityLombokModel)
    @Override
    public String toString() {
        return "${entity}{" +
    #foreach($field in $table.fields)
        #if($field_index == 0)
            "${field.propertyName}=" + ${field.propertyName} +
        #else
            ", ${field.propertyName}=" + ${field.propertyName} +
        #end
    #end
        "}";
    }
#end
}

2、添加依赖 mybatis-plus-generator 代码生成器的依赖 

<!-- MySQL Connector -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>
        <!-- MyBatis Plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.5</version>
        </dependency>
        <!-- Code Generator -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.5</version>
        </dependency>
        <!--velocity代码生成使用模板 -->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.3</version>
        </dependency>

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.25</version>
        </dependency>
        <dependency>
            <groupId>org.jetbrains</groupId>
            <artifactId>annotations</artifactId>
            <version>16.0.3</version>
            <scope>compile</scope>
        </dependency>

3、编写生成器代码 3个 类

入口: AutoGeneratorUtils ;
自定义文件名:DefVelocityTemplateEngine ;
所有 Entity的父类:CommonEntity (名字感觉不是太直观)

1)入口: AutoGeneratorUtils ,编写完直接运行

package com.demo;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.generator.config.builder.CustomFile;

import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.demo.common.pojo.CommonEntity;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * IDaaS后台管理系统代码生成工具
 * 代码生成器,基于mybatis-plus-generator,需要引入以下两个依赖
 * implementation("com.baomidou:mybatis-plus-generator:3.5.2")
 * implementation("org.freemarker:freemarker:2.3.32")
 */
public class AutoGeneratorUtils {

    /**
     * 指定模块名
     **/
    private static String MODULE_NAME = "sys";
    /**
     * 指定表明
     **/
    private static String TABLE_NAME = "sys_logininfor";
    /**
     * 你的所属上级菜单 ID
     **/
    private static String PARENT_MENU_ID = "b648b666-9af5-4bfa-8036-7d09f3439c2c";
    /**
     * 过滤表前缀
     **/
    private static String[] TABLE_PREFIX = {"buz_", "t_", "c_"};
    /**
     * 作者
     **/
    private static String AUTHOR = "admin";

    /**
     * 数据源信息
     */
    private static String JDBC_URL = "jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8";
    private static String USER_NAME = "root";
    private static String PASSWORD = "123456";

    /**
     * 包设置
     */
    private static String PARENT = "com.ruoyi.web";
    private static String MAPPER_XML_PATH = "/resources/mapper";
    private static String VUE_PATH = "/vue/views/";
    private static String VUE_JS_PATH = "/vue/api";
    private static String MENU_SQL_PATH = "/sql";

    /**
     * 代码输出路径
     */
    private static String OUTPUT_DIR = "D://temp";

    public static void main(String[] args) {
        String entityPath = getEntityPath();

        FastAutoGenerator.create(JDBC_URL, USER_NAME, PASSWORD)
                // 全局配置
                .globalConfig(builder -> {
                    builder.author(AUTHOR) // 设置作者
                            //.enableSwagger() // 开启 swagger 模式
                            .dateType(DateType.ONLY_DATE) //设置全局的时间类型为 Date
                            .outputDir(OUTPUT_DIR); // 指定输出目录
                })
                // 包配置
                .packageConfig(builder -> {
                    builder.parent(PARENT) // 设置父包名
                            .moduleName(MODULE_NAME) // 设置父包模块名
                            .pathInfo(Collections.singletonMap(OutputFile.xml, OUTPUT_DIR + MAPPER_XML_PATH)); // 设置mapperXml生成路径
                })
                // 策略配置
                .strategyConfig(builder -> {
                    builder.addInclude(TABLE_NAME) // 设置需要生成的表名
                            .addTablePrefix(TABLE_PREFIX) // 设置过滤表前缀
                            // 实体策略配置
                            .entityBuilder()
                            .superClass(CommonEntity.class) //设置所有实体类的父类
                            .enableLombok() //启用lombok get set
                            // Controller策略配置
                            .controllerBuilder()
                            .enableFileOverride() // 覆盖已生成文件
                            .enableRestStyle(); //开启生成@RestController 控制器


                })
                .templateEngine(new DefVelocityTemplateEngine())// 使用默认的是 VelocityTemplateEngine 引擎模板,也可以是 FreemarkerTemplateEngine
                // 模板配置
                .templateConfig(builder -> {
                    builder.entity("/templates/java/entity.java.vm")
                            .service("/templates/java/service.java.vm")
                            .serviceImpl("/templates/java/serviceImpl.java.vm")
                            .mapper("/templates/java/mapper.java.vm")
                            .xml("/templates/xml/mapper.xml.vm")
                            .controller("/templates/java/controller.java.vm");

                })
                .injectionConfig(consumer -> {

                    // vo
                    consumer.customFile(new CustomFile.Builder().fileName("Param.java").packageName("entity.vo").templatePath("/templates/java/entityParam.java.vm").build());

                    // 前端
                    consumer.customFile(new CustomFile.Builder().fileName("Index.vue").filePath(OUTPUT_DIR + VUE_PATH + "/" + MODULE_NAME + "/" + entityPath).templatePath("/templates/vue/Index.vue.vm").build());
                    consumer.customFile(new CustomFile.Builder().fileName("Form.vue").filePath(OUTPUT_DIR + VUE_PATH + "/" + MODULE_NAME + "/" + entityPath).templatePath("/templates/vue/Form.vue.vm").build());
                    consumer.customFile(new CustomFile.Builder().fileName("Import.vue").filePath(OUTPUT_DIR + VUE_PATH + "/" + MODULE_NAME + "/" + entityPath).templatePath("/templates/vue/Import.vue.vm").build());

                    consumer.customFile(new CustomFile.Builder().fileName(".js").filePath(OUTPUT_DIR + VUE_JS_PATH + "/" + MODULE_NAME).templatePath("/templates/js/api.js.vm").build());
                    consumer.customFile(new CustomFile.Builder().fileName(".sql").filePath(OUTPUT_DIR + MENU_SQL_PATH).templatePath("/templates/sql/sql.vm").build());

                    //添加自定义工具类,主要用 tool.lowerFirst(字符)、upperFirst(字符)、isEmpty(字符)、isNotEmpty(字符)、subBefore(字符串,分隔符,true)
                    Map<String, Object> toolMap = new HashMap<>();
                    toolMap.put("tool", new StrUtil());
                    //json工具,方便判断对象中存在的属性 jsonTool.toJsonStr(对象)
                    toolMap.put("jsonTool", new JSONUtil());
                    //正则表达式工具,方便剔除不用的类 reTool.isMatch(正则表达式,内容),reTool.contains(正则表达式,内容)
                    toolMap.put("reTool", new ReUtil());
                    //添加自定义变量
                    toolMap.put("parentMenuId", PARENT_MENU_ID);
                    consumer.customMap(toolMap);
                })
                .execute();
    }

    public static String getEntityPath() {
        String entityPath = ObjectUtil.clone(TABLE_NAME);

        if (ArrayUtil.isNotEmpty(TABLE_PREFIX)) {
            for (int i = 0; i < TABLE_PREFIX.length; i++) {
                entityPath = StrUtil.removeAll(entityPath, TABLE_PREFIX[i]);
            }
        }

        //转换驼峰规则
        entityPath = StrUtil.toCamelCase(entityPath);

        //首字母小写
        return StrUtil.lowerFirst(entityPath);
    }
}

2)自定义文件名:DefVelocityTemplateEngine ;

package com.demo;

import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.builder.CustomFile;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.util.List;
import java.util.Map;

public class DefVelocityTemplateEngine extends VelocityTemplateEngine {

    @Override
    protected void outputCustomFile(@NotNull List<CustomFile> customFiles, @NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
        String entityName = tableInfo.getEntityName();
        String firstLowerEntityName = StrUtil.lowerFirst(entityName);

        String parentPath = this.getPathInfo(OutputFile.parent);

        customFiles.forEach((file) -> {
            String filePath = StrUtil.isNotBlank(file.getFilePath()) ? file.getFilePath() : parentPath;
            if (StrUtil.isNotBlank(file.getPackageName())) {
                filePath = filePath + File.separator + file.getPackageName();
                filePath = filePath.replaceAll("\\.", "\\" + File.separator);
            }

            String fileName = StrUtil.nullToEmpty(file.getFileName());
            fileName = filePath + File.separator + (ReUtil.isMatch(".*\\.(js|vue)$", fileName) ? firstLowerEntityName : entityName) + fileName;
            this.outputFile(new File(fileName), objectMap, file.getTemplatePath(), file.isFileOverride());
        });
    }
}

3)所有 Entity的父类:CommonEntity

仅做演示啥都没有

package com.demo.common.pojo;

public class CommonEntity {
}

4、运行效果

其中导入导出逻辑采用easyexcel:参考文档

easyExcel 导入、导出Excel 封装公共的方法-CSDN博客文章浏览阅读84次,点赞4次,收藏2次。*** 导出采购订单列表*/@Log(title = "采购订单", businessType = BusinessType.EXPORT)List listDatas = 获取数据的service方法nmwDate.setFileName("历史生产数据");https://blog.csdn.net/qq_26408545/article/details/136654488

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

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

相关文章

ES6基础6

Promise对象 Promise的含义 所谓Promise&#xff0c;简单说就是一个容器&#xff0c;里面保存着某个未来才会结束的事件&#xff08;通常是一个异步操作&#xff09;的结果。从语法上说&#xff0c;Promise是一个对象&#xff0c;从它可以获取异步操作的消息。Promise提供统一的…

深度学习笔记_8隐马尔可夫模型(HMM)

隐马尔可夫模型(Hidden Markov Model, HMM)是一种统计模型&#xff0c;在语音识别、行为识别、NLP、故障诊断等领域具有高效的性能。 HMM是关于时序的概率模型&#xff0c;描述一个含有未知参数的马尔可夫链所生成的不可观测的状态随机序列&#xff0c;再由各个状态生成观测随…

设计模式 -- 1:简单工厂模式

目录 代码记录代码部分 代码记录 设计模式的代码注意要运用到面向对象的思想 考虑到紧耦合和松耦合 把具体的操作类分开 不让其互相影响&#xff08;注意这点&#xff09; 下面是UML类图 代码部分 #include <iostream> #include <memory> // 引入智能指针的头文…

linux 模拟shell

&#x1f493;博主CSDN主页:麻辣韭菜-CSDN博客&#x1f493;   ⏩专栏分类&#xff1a;http://t.csdnimg.cn/G90eI⏪   &#x1f69a;代码仓库:Linux: Linux日常代码练习&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多Linux知识   &#x1f51d;&#x1f5…

[linux] socket 非阻塞模式使用注意事项

在使用 socket 的一些 api 的时候&#xff0c;默认情况下都是阻塞模式。比如使用 tcp socket 时&#xff0c;客户端调用 connect() 创建连接&#xff0c;connect() 返回的时候要么是创建连接成功了&#xff0c;要么是出现了错误&#xff0c;反正 connect() 返回的时候结果是确定…

Unsupervised RL:METRA: Scalable Unsupervised RL with Metric-Aware Abstraction

ICLR 2024 Oral paper Intro 无监督RL旨在发现潜在的行为帮助提高下游任务效率以往方法集中于探索以及基于互信息的技能发现(skill)。然而去前者在高危复杂空间实现困难&#xff0c;后者也容易因为缺乏激励导致探索能力不足。本文提出METRA核心观点认为与其在复杂状态空间处理…

OGNL表达式

文章目录 一、简介二、快速入门三、详细使用3.1 基本数据类型3.2 对象类型3.3 List集合3.4 Set集合3.5 Map集合3.6 数组3.7 静态调用3.8 算术运算3.9 逻辑运算3.10 同时执行多个表达式3.11 位运算 Ognl使用总结 - 源链接在此 >> 一、简介 OGNL&#xff08;Object-Graph…

小兔鲜鲜项目(前端vue3)

成果图 大家喜欢给一个赞被&#xff0c; 项目地址&#xff1a;gitee 注意&#xff1a;项目克隆下去之后先运行 npm i之后安装项目插件包之后在npm run dev 运行就可以了

“成像光谱遥感技术中的AI革命:ChatGPT应用指

遥感技术主要通过卫星和飞机从远处观察和测量我们的环境&#xff0c;是理解和监测地球物理、化学和生物系统的基石。ChatGPT是由OpenAI开发的最先进的语言模型&#xff0c;在理解和生成人类语言方面表现出了非凡的能力。本文重点介绍ChatGPT在遥感中的应用&#xff0c;人工智能…

python读取execl里的图片

正常的读取图片 from openpyxl import load_workbook from PIL import Imagefrom openpyxl import load_workbook wb load_workbook(rC:\Users\Administrator\Downloads\output1111.xlsx) ws wb[wb.sheetnames[0]] for image in ws._images:data image.anchor._fromif image…

深入学习默认成员函数——c++指南

前言&#xff1a;类和对象是面向对象语言的重要概念。 c身为一门既面向过程&#xff0c;又面向对象的语言。 想要学习c&#xff0c; 首先同样要先了解类和对象。 本节就类和对象的几种构造函数相关内容进行深入的解析。 目录 类和对象的基本概念 封装 类域和类体 访问限定符…

家长应如何培养孩子对人工智能(AI)的兴趣?无际Ai分享

随着科技的飞速发展&#xff0c;人工智能已经成为了当今社会的重要组成部分。然而&#xff0c;在中小学阶段&#xff0c;很少有学校系统地对学生进行人工智能方面的教育。作为普通家庭的家长&#xff0c;我们可以通过一些方法来激发孩子对人工智能的兴趣&#xff0c;让他们在这…

网络工程师——2024自学

一、怎样从零开始学习网络工程师 当今社会&#xff0c;人人离不开网络。整个IT互联网行业&#xff0c;最好入门的&#xff0c;网络工程师算是一个了。 什么是网络工程师呢&#xff0c;简单来说&#xff0c;就是互联网从设计、建设到运行和维护&#xff0c;都需要网络工程师来…

第7讲:数组和函数实践:扫雷游戏

第7讲&#xff1a;数组和函数实践&#xff1a;扫雷游戏 1. 扫雷游戏分析和设计1.1 扫雷游戏的功能说明1.2 游戏的分析和设计1.2.1 数据结构的分析1.2.2 文件结构设计 2. 扫雷游戏的代码实现3. 扫雷游戏的扩展 1. 扫雷游戏分析和设计 1.1 扫雷游戏的功能说明 • 使用控制台实现…

Edu 12 --- Simple Subset -- 题解 (一个比较巧妙的思维算法题)

Simple Subset&#xff1a; 题解&#xff1a; 思路解析&#xff1a; 题目要求任意两个数的和为质数&#xff0c;那我们最坏情况就是任意选择一个数&#xff0c;此时子集为最大。 如果子集中有两个奇数或者偶数&#xff0c;他们两个之和一定会被2整除&#xff0c;那么我们只能…

keilC51明明已经定义的变量却报错未定义与期待asm

文章目录 keil_C51采用的是C89标准&#xff1a;C89变量定义标准&#xff1a;程序块&#xff1a; expected __asm&#xff1a;已经定义某个变量却报错未定义该变量&#xff1a;从汇编语言中看&#xff1a; keil_C51采用的是C89标准&#xff1a; C89变量定义标准&#xff1a; 1…

Web框架开发-HTTP协议

一、HTTP协议简介 HTTP协议是Hyper Text Transfer Protocol&#xff08;超文本传输协议&#xff09;的缩写,是用于万维网&#xff08;WWW:World Wide Web &#xff09;服务器与本地浏览器之间传输超文本的传送协议。 HTTP是一个属于应用层的面向对象的协议&#xff0c;由于其简…

C while 循环

只要给定的条件为真&#xff0c;C 语言中的 while 循环语句会重复执行一个目标语句。 语法 C 语言中 while 循环的语法&#xff1a; while(condition) {statement(s); }在这里&#xff0c;statement(s) 可以是一个单独的语句&#xff0c;也可以是几个语句组成的代码块。 co…

【C++进阶】C++多态概念详解

C多态概念详解 一&#xff0c;多态概念二&#xff0c;多态的定义2.1 多态构成的条件2.2 什么是虚函数2.3 虚函数的重写2.3.1 虚函数重写的特例2.3.2 override和final 2.4 重载和重写&#xff08;覆盖&#xff09;和重定义&#xff08;隐藏&#xff09;的区别 三&#xff0c;抽象…

数据库规范化设计案例解析

1.介绍 数据库规范化设计是数据库设计的一种重要方法&#xff0c;旨在减少数据库中的冗余数据&#xff0c;提高数据的一致性&#xff0c;确保数据依赖合理&#xff0c;从而提高数据库的结构清晰度和维护效率。规范化设计通过应用一系列的规范化规则&#xff08;或称“范式”&a…