引入依赖

        <dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
<!--糊涂工具包-->
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-core -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>5.7.20</version>
</dependency>

MyBatisPlus提高高度封装好的代码生成器模块,只需要简单的几行代码就能实现。同时也可以根据自己的需求灵活的通过模板话的方式生成代码。下面我们分别通过这两种方式来了解一些。

简单的代码生成

package com.didiplus;

import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import org.junit.jupiter.api.Test; import java.util.Collections; /**
* Author: didiplus
* Email: 972479352@qq.com
* CreateTime: 2022/5/6
* Desc:快速生成
*/
public class FastAutoGeneratorTest { @Test
public void fastAutoGeneratorTest(){
String url="jdbc:mysql://127.0.0.1:3306/didiadmin?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true";
FastAutoGenerator.create(url,"root","123456")
.globalConfig(builder -> {
builder.author("didiplus") // 设置作者
.enableSwagger() //开启 swagger 模式
.outputDir("D://autocode");// 指定输出目录
})
.packageConfig(builder -> {
builder.parent("com.didiplus.models") // 设置父包名
.moduleName("sys") // 设置父包模块名
.pathInfo(Collections.singletonMap(OutputFile.xml,"D://autocode/xml"));
})
.strategyConfig(builder -> {
builder.addInclude("sys_dict_data") // 设置需要生成的表名
.addTablePrefix("t_","c_") ; // 设置过滤表前缀
})
// .templateEngine(new FreemarkerTemplateEngine()) 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
}

运行以上代码,会自动的在D盘生成代码,但是,生成的代码只是最基本的模板。





以上生成的代码都是基于MybatisPlus代码生成默认模板去生成的。适合绝大多数场景。我们也可以根据自己的模板文件去生成代码的。

自定义模板生成代码

实现思路

  • 从数据库中读取表的相关信息和表的相关字段
  • 定义相对于的模板文件
  • 组装模板属性

定义代码生成常量

这些常量主要用户后期在组装模板时,把数据库类型转换成Java数据类型需要用到的。

package com.didiplus.constant;

/**
* Author: didiplus
* Email: 972479352@qq.com
* CreateTime: 2022/5/6
* Desc: 码 生 成 通 用 常 量
*/
public class GenerateConstant { /**
* 数据库字符串类型
*/
public static final String[] COLUMN_TYPE_STR = {"char", "varchar", "nvarchar", "varchar2", "tinytext", "text", "mediumtext", "longtext"};
/**
* 数据库时间类型
*/
public static final String[] COLUMN_TYPE_TIME = {"datetime", "time", "date", "timestamp"};
/**
* 数据库数字类型
*/
public static final String[] COLUMN_TYPE_NUMBER = {"tinyint", "smallint", "mediumint", "int", "number", "integer", "bit"};
/**
* 数据库bigint类型
*/
public static final String[] COLUMN_TYPE_BIGINT = {"bigint"};
/**
* 数据库float类型
*/
public static final String[] COLUMN_TYPE_FLOAT = {"float"};
/**
* 数据库double类型
*/
public static final String[] COLUMN_TYPE_DOUBLE = {"double"};
/**
* 数据库decimal类型
*/
public static final String[] COLUMN_TYPE_DECIMAL = {"decimal"}; /**
* 字符串类型
*/
public static final String TYPE_STRING = "String"; /**
* 整型
*/
public static final String TYPE_INTEGER = "Integer"; /**
* 长整型
*/
public static final String TYPE_LONG = "Long"; /**
* 浮点型
*/
public static final String TYPE_DOUBLE = "Double"; /**
* 高精度计算类型
*/
public static final String TYPE_BIGDECIMAL = "BigDecimal"; /**
* 时间类型
*/
public static final String TYPE_DATE = "Date";
}

全局配置

    /**
* 全局配置
*/
private GlobalConfig.Builder globalConfig() {
String projectPath = System.getProperty("user.dir");
return new GlobalConfig.Builder()
.fileOverride() // 覆盖已生成文件
.disableOpenDir() // 禁止打开输出目录 默认值:true
.author("didiplus") //作者名
.outputDir(projectPath+"/src/main/resources/autocode") // 指定输出目录
.enableSwagger(); // 开启 swagger 模式 默认值:false
}

定义生成代码模板的路径

    /**
* 模板配置
*/
private TemplateConfig.Builder templateConfig() {
return new TemplateConfig.Builder()
.entity("/templates/vm/entity.java")
.mapper("/templates/vm/mapper.java")
.service("/templates/vm/service.java")
.serviceImpl("/templates/vm/serviceimpl.java")
.controller("/templates/vm/controller.java")
.xml("/templates/vm/mapper.xml");
}

以上的函数是声明代码生成根据这些模板去生成对应的模板。

定义各文件生成存储路径

    /**
* 包配置
*/
private PackageConfig.Builder packageConfig() {
return new PackageConfig.Builder()
.parent(packageName)
.moduleName(moduleName)
.entity("domain.entity")
.mapper("mapper")
.service("service")
.serviceImpl("service.impl")
.xml("mapper.xml")
.controller("controller");
}

数据源配置

    /**
* 数据源配置
*/
private static final DataSourceConfig DATA_SOURCE_CONFIG = new DataSourceConfig
.Builder("jdbc:mysql://127.0.0.1:3306/didiadmin?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true","root","123456")
.build();

配置策略

    /**
* 策略配置
*/
private StrategyConfig.Builder strategyConfig() {
return new StrategyConfig.Builder()
.addInclude(tableName);
}

组装模板属性

    /**
* 注入配置
*/
private InjectionConfig.Builder injectionConfig(){
Map<String, Object> map = new HashMap<>();
setAttr(tableName, DATA_SOURCE_CONFIG, map);
return new InjectionConfig.Builder().customMap(map); } /**
* 组装模板属性
*
* @param tableName 表名
* @param dataSourceConfig 数据源
* @param map 模板里面 自定义的属性
* @param 表前缀
*/
private void setAttr(String tableName, DataSourceConfig dataSourceConfig, Map<String, Object> map ){
List<Map<String, Object>> columns = new ArrayList<>();
// 获取表信息sql
String tableSql = "select table_name , table_comment from information_schema.tables " +
"where table_schema = (select database()) and table_name = '" + tableName + "'";
// 获取字段信息sql
String columnSql = "select column_name , data_type , column_comment from information_schema.columns " +
"where table_name = '" + tableName + "' and table_schema = (select database()) and column_name != 'id_new'"; // 利用现有的dataSourceConfig来获取数据库连接,查询表字段及备注等信息
try(
Connection conn = dataSourceConfig.getConn();
PreparedStatement psTable = conn.prepareStatement(tableSql);
ResultSet rsTable = psTable.executeQuery();
PreparedStatement pscolumns= conn.prepareStatement(columnSql);
ResultSet rscolumns = pscolumns.executeQuery();
){
if(rsTable.next()){
String table_name = rsTable.getString("table_name");
map.put("tableName",table_name);
map.put("comment",rsTable.getString("table_comment"));
// 类名 大驼峰
map.put("upperClassName", StrUtil.upperFirst(StrUtil.toCamelCase(table_name)));
// 对象名 小驼峰
map.put("lowerClassName",StrUtil.toCamelCase(table_name));
}
while (rscolumns.next()){
Map<String, Object> columnMap = new HashMap<>();
// 列名字、数据类型、java属性名字、java属性类型、备注
columnMap.put("column_name",rscolumns.getString("column_name"));
columnMap.put("data_type",rscolumns.getString("data_type"));
columnMap.put("javaLowerAttrName",StrUtil.toCamelCase(rscolumns.getString("column_name")));
columnMap.put("javaAttrType",columnTypeToJavaType(rscolumns.getString("data_type")));
columnMap.put("column_comment", rscolumns.getString("column_comment"));
columns.add(columnMap);
}
} catch (Exception e) {
log.info("----------sql执行出错");
e.printStackTrace();
}
map.put("columns",columns);
map.put("datetime", DateUtil.now());
map.put("packageName", packageName);
map.put("moduleName", moduleName);
} /**
* 数据库类型转换为java类型
*
* @param columnType 数据库类型
* @return java类型
*/
private String columnTypeToJavaType(String columnType) {
if(StrUtil.isNotEmpty(columnType)){
if(Arrays.asList(GenerateConstant.COLUMN_TYPE_STR).contains(columnType)){
return GenerateConstant.TYPE_STRING;
}
if(Arrays.asList(GenerateConstant.COLUMN_TYPE_TIME).contains(columnType)){
return GenerateConstant.TYPE_DATE;
}
if (Arrays.asList(GenerateConstant.COLUMN_TYPE_NUMBER).contains(columnType)) {
return GenerateConstant.TYPE_INTEGER;
}
if (Arrays.asList(GenerateConstant.COLUMN_TYPE_BIGINT).contains(columnType)) {
return GenerateConstant.TYPE_LONG;
}
if (Arrays.asList(GenerateConstant.COLUMN_TYPE_FLOAT).contains(columnType)) {
return GenerateConstant.TYPE_DOUBLE;
}
if (Arrays.asList(GenerateConstant.COLUMN_TYPE_DOUBLE).contains(columnType)) {
return GenerateConstant.TYPE_DOUBLE;
}
if (Arrays.asList(GenerateConstant.COLUMN_TYPE_DECIMAL).contains(columnType)) {
return GenerateConstant.TYPE_BIGDECIMAL;
}
}
return null;
}

定义对应的模板文件

在项目的资源文件夹templats中创建vm文件夹存放模板文件

entity.java.vm

package ${packageName}.${moduleName}.domain.entity;
#set($list=["createBy","createTime","createName", "updateBy", "updateName","updateTime", "deleteFlag"])
import com.didiplus.common.base.BaseDomain;
import lombok.Data;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import java.util.Date; import com.baomidou.mybatisplus.annotation.TableName; /**
* @author ${author}
* @date ${datetime}
*
* @description ${comment}(${upperClassName}实体类)
*/
@Data
@TableName("${tableName}")
@ApiModel(value = "${comment}", description = "${comment}对象 ${lowerClassName}")
public class ${upperClassName}Entity extends BaseDomain { #foreach ($column in $columns)
## 排除父类字段
#if($list.contains($column.javaLowerAttrName))
#else
/**
* $column.column_comment
*/
@ApiModelProperty(value = "$column.column_comment")
private $column.javaAttrType $column.javaLowerAttrName;
#end
#end
}

mapper.java.vm

package ${packageName}.${moduleName}.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import ${packageName}.${moduleName}.domain.entity.${upperClassName}Entity;
import org.apache.ibatis.annotations.Mapper; /**
* @author ${author}
* @date ${datetime}
*
* @description ${comment}
*/
@Mapper
public interface ${upperClassName}Mapper extends BaseMapper<${upperClassName}Entity> { }

mapper.xml.vm

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="${packageName}.${moduleName}.mapper.${upperClassName}Mapper"> <resultMap id="${lowerClassName}Map" type="${packageName}.${moduleName}.domain.${upperClassName}">
#foreach($column in $columns)
<result column="${column.column_name}" property="${column.javaLowerAttrName}"/>
#end
</resultMap>
</mapper>

service.java.vm

package ${packageName}.${moduleName}.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import ${packageName}.${moduleName}.domain.entity.${upperClassName};
import com.didiplus.common.web.domain.PageDomain; /**
* @author ${author}
* @date ${datetime}
*
* @description ${comment}
*/
public interface I${upperClassName}Service extends IService<${upperClassName}Entity> { /**
* 分页查询
* @param pageDomain
* @return
*/
IPage<${upperClassName}Entity> page(PageDomain pageDomain); }

serviceImpl.java.vm

package ${packageName}.${moduleName}.service.impl;

import com.didiplus.common.web.domain.PageDomain;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import ${packageName}.${moduleName}.domain.entity.${upperClassName}Entity;
import ${packageName}.${moduleName}.mapper.${upperClassName}Mapper;
import ${packageName}.${moduleName}.service.I${upperClassName}Service;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
/**
* @author ${author}
* @date ${datetime}
*
* @description ${comment}
*/
@Service
public class ${upperClassName}ServiceImpl extends ServiceImpl<${upperClassName}Mapper, ${upperClassName}Entity> implements I${upperClassName}Service { @Resource
${upperClassName}Mapper ${lowerClassName}Mapper;
@Override
public IPage<${upperClassName}Entity> page(PageDomain pageDomain) {
IPage<${upperClassName}Entity> page = new Page<>(pageDomain.getPage(),pageDomain.getLimit());
return ${lowerClassName}Mapper.selectPage(page,null);
}
}

controller.java.vm

package ${packageName}.${moduleName}.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import ${packageName}.${moduleName}.domain.entity.${upperClassName}Entity;
import ${packageName}.${moduleName}.service.I${upperClassName}Service;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import com.didiplus.common.web.domain.PageDomain;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.didiplus.common.base.ValidGroup;
import javax.annotation.Resource; /**
* @author ${author}
* @date ${datetime}
*
* @description ${comment}
*/
@Slf4j
@RestController
@RequestMapping("/${lowerClassName}")
@Api(value = "${lowerClassName}", tags = "${comment}管理模块")
public class ${upperClassName}Controller { @Resource
private I${upperClassName}Service ${lowerClassName}Service; /**
* 分页查询
* @param pageDomain 分页对象
* @param ${lowerClassName}Entity ${comment}
* @return IPage
*/
@ApiOperation(value = "分页查询", notes = "分页查询")
@GetMapping("/page")
public IPage get${upperClassName}Page(@RequestBody PageDomain pageDomain) {
return ${lowerClassName}Service.page(pageDomain);
} /**
* 新增${comment}
* @param ${lowerClassName}Entity ${comment}
* @return Result
*/
@ApiOperation(value = "新增${comment}", notes = "新增${comment}")
@PostMapping
public String save(@Validated(ValidGroup.Crud.Create.class) @RequestBody ${upperClassName}Entity ${lowerClassName}Entity) {
return ${lowerClassName}Service.save(${lowerClassName}Entity)? "添加成功":"添加失败"; } /**
* 修改${comment}
* @param ${lowerClassName}Entity ${comment}
* @return Result
*/
@ApiOperation(value = "修改${comment}", notes = "修改${comment}")
@PutMapping
public String updateById(@Validated(ValidGroup.Crud.Update.class) @RequestBody ${upperClassName}Entity ${lowerClassName}Entity) {
return ${lowerClassName}Service.updateById(${lowerClassName}Entity)? "修改成功":"修改失败"; } /**
* 通过id删除${comment}
* @param id id
* @return Result
*/
@ApiOperation(value = "通过id删除${comment}", notes = "通过id删除${comment}")
@DeleteMapping("/{id}")
public String removeById(@PathVariable Integer id) {
return ${lowerClassName}Service.removeById(id)? "删除成功":"删除失败";
}
}

定义启动类

    @Test
public void generatorCode(){ AutoGenerator generator = new AutoGenerator(DATA_SOURCE_CONFIG);
generator.strategy(strategyConfig().build());
generator.injection(injectionConfig().build());
generator.global(globalConfig().build());
generator.template(templateConfig().build());
generator.packageInfo(packageConfig().build());
generator.execute(); }

执行以上函数就可以自动生成代码了,如下图:

目前代码自动生成器只是一个脚本方式运行,后续我们会把它集成到页面上,通过图形界面的方式去操作。好了今天就分享到这里了,有什么问题欢迎留意。更多关注公众号“攻城狮成长日记”。

专门为小白准备的入门级mybatis-plus-generator代码自动生成器,提高开发效率。值得收藏的更多相关文章

  1. Mybatis最入门---代码自动生成(generatorConfig.xml配置)

    [一步是咫尺,一步即天涯] 经过前文的叙述,各位看官是不是已经被Mybatis的强大功能给折服了呢?本文我们将介绍一个能够极大提升我们开发效率的插件:即代码自动生成.这里的代码自动生成包括,与数据库一 ...

  2. Mybatis Generator代码自动生成(实体类、dao层、映射文件)

    写了一段时间增删改查有点厌烦,自己找了下网上的例子鼓捣了下自动生成. 首先得有一个配置文件: generatorConfig.xml <?xml version="1.0" ...

  3. MyBatis Generator代码自动生成工具的使用

    MyBatis Generator MyBatis Generator有三种使用方式,分别是maven插件形式.命令行形式以及eclipse插件形式.我在这里使用的是命令行的形式(主要是命令行形式比较 ...

  4. MyBatis数据库测试代码自动生成

    <!-- generatorConfig.xml配置,其中:<plugin type="org.mybatis.generator.plugins.ToStringPlugin& ...

  5. mybatis结合generator进行分页插件PluginAdapter开发

    使用org.mybatis.generator生成UserExample时,无法进行分页,使用下面这个类运行generator便可以生成分页相关的属性了 package org.mybatis.gen ...

  6. Mybatis 代码自动生成(generatorConfig.xml配置)

    博客推荐: Mybatis最入门---代码自动生成(generatorConfig.xml配置) MyBatis Generator generatorConfig.xml配置详解 pom.xml&l ...

  7. 写给小白看的入门级 Java 基本语法,强烈推荐

    之前写的一篇我去阅读量非常不错,但有一句留言深深地刺痛了我: 培训班学习半年,工作半年,我现在都看不懂你这篇文章,甚至看不下去,对于我来说有点深. 从表面上看,这句话有点讽刺我的文章写得不够通俗易懂的 ...

  8. MyBatis代码自动生成(利用eclipse插件)

    上一篇文章已经介绍了利用命令的方式自动生成mybatis代码,但是每次都去运行cmd命令感觉还是有点麻烦,所以找了些资料发现eclipse里面也可以安装插件自动生成代码,下面简单介绍一下,也是给自己以 ...

  9. MyBatis代码自动生成

    MyBatis的代码自动生成的功能,由于MyBatis属于一种半自动的ORM框架,所以主要的工作就是配置Mapping映射文件,但是由于手写映射文件很容易出错,所以可利用MyBatis生成器自动生成实 ...

随机推荐

  1. final、finalize 和 finally 的不同之处?

    final 是一个修饰符,可以修饰变量.方法和类.如果 final 修饰变量,意味着该 变量的值在初始化后不能被改变.finalize 方法是在对象被回收之前调用的方法, 给对象自己最后一个复活的机会 ...

  2. JavaScript的取值小技巧之“中括号[]取值法”

    一.简介 做下记录,今天看了一篇很有意思的文章,学到了这个取值的小技巧 正常的话我们一般都是用对象直接去'.'对应的属性名(也就是键值对的键)来获取对应的值 这里记录的是另一种取值方式,他是采用中括号 ...

  3. (stm32f103学习总结)—USART串口通信

    一. USART简介 USART即通用同步异步收发器,它能够灵活地与外部设备进行全双工 数据交换,满足外部设备对工业标准 NRZ 异步串行数据格式的要求. UART即通用异步收发器,它是在USART基 ...

  4. s函数

    Matlab 中S-函数模板翻译 10.0 基础知识 (1)Simulink仿真过程 Simulnk仿真分为两步:初始化.仿真循环.仿真是由求解器控制的,求解器主要作用是:计算模块输出.更新模块离散状 ...

  5. STM32 标准库

    CMSIS 标准及库层次关系 因为基于Cortex 系列芯片采用的内核都是相同的,区别主要为核外的片上外设的差异,这些差异却导致软件在同内核,不同外设的芯片上移植困难.为了解决不同的芯片厂商生产的Co ...

  6. 从零开始开发一款H5小游戏(三) 攻守阵营,赋予粒子新的生命

    本系列文章对应游戏代码已开源 Sinuous game. 每个游戏都会包含场景和角色.要实现一个游戏角色,就要清楚角色在场景中的位置,以及它的运动规律,并能通过数学表达式表现出来. 场景坐标 canv ...

  7. mpvue打包没有app.json等配置文件的解决方法

    问题 一早上折腾了1个小时,小程序始终提示查找不到'app.json'文件.mpvue重新打包,光生成内容文件无配置文件. 解决办法 出错原因:版本问题 只需要把packpage.json里的mpvu ...

  8. 微信小程序 使用filter过滤器几种方式

    由于微信小程序 技术生态比较闭合,导致很多 现代前端框架很多积累出的成果都没有实现(可能未来会逐一实现). 用惯了现代 再耍小程序 总感觉很不顺手. 需要结果的请直接看最后的WXS View Filt ...

  9. 第一天·浏览器内核及Web标准

    一·浏览器及浏览器内核 1.常见的浏览器 (1)IE浏览器 IE是微软公司旗下浏览器,是目国内用户量最多的浏览器.IE诞生于1994年,当时微软为了对抗市场份额占据将近百分之九十的网景Netscape ...

  10. 前端如何通过js判断浏览器的类型(忽略版本)web html css javascript

    每个页面浏览器会实例出一个window对象,在window对象下有一个属性navigator,navigator本身是一个对象,navigator对象上有一个属性userAgent里面包含了当前浏览器 ...