入门级mybatis-plus-generator代码自动生成器,提高开发效率。值得收藏

简介: 入门级mybatis-plus-generator代码自动生成器

我们使用代码生成器的目的主要是提供开发效率,减少重复性的工作。在使用Springboot开发过程中,我们使用代码生成器把大概的模板生成出来,再根据自己的业务特征进行改动。这样就可以提高效率

引入依赖

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

简单的代码生成

```java
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盘生成代码,但是,生成的代码只是最基本的模板。
![](https://ucc.alicdn.com/images/user-upload-01/img_convert/b7661c3a598dc55730fb27348949a7d7.png#crop=0&crop=0&crop=1&crop=1&id=lwq3v&originHeight=240&originWidth=842&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)
![](https://ucc.alicdn.com/images/user-upload-01/img_convert/514c62004285193c4efdf71e5180fa28.png#crop=0&crop=0&crop=1&crop=1&id=IK0TJ&originHeight=359&originWidth=893&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)
以上生成的代码都是基于MybatisPlus代码生成默认模板去生成的。适合绝大多数场景。我们也可以根据自己的模板文件去生成代码的。
# 自定义模板生成代码
## 实现思路

- 从数据库中读取表的相关信息和表的相关字段
- 定义相对于的模板文件
- 组装模板属性
## 定义代码生成常量
这些常量主要用户后期在组装模板时,把数据库类型转换成Java数据类型需要用到的。
```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 {
   
   mathJaxContainer[0]}{
   
   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 ({
   
   mathJaxContainer[3]}columns)
        ##    排除父类字段
        #if({
   
   mathJaxContainer[4]}column.javaLowerAttrName))
        #else
            /**
             * $column.column_comment
             */
            @ApiModelProperty(value = "$column.column_comment")
            private {
   
   mathJaxContainer[5]}column.javaLowerAttrName;
        #end
    #end
}

mapper.java.vm

package {
   
   mathJaxContainer[6]}{
   
   moduleName}.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import {
   
   mathJaxContainer[7]}{
   
   moduleName}.domain.entity.${
   
   upperClassName}Entity;
import org.apache.ibatis.annotations.Mapper;

/**
 * @author ${author}
 * @date ${datetime}
 *
 * @description ${comment}
 */
@Mapper
public interface {
   
   mathJaxContainer[8]}{
   
   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({
   
   mathJaxContainer[12]}columns)
            <result column="${column.column_name}" property="${column.javaLowerAttrName}"/>
        #end
    </resultMap>
</mapper>

service.java.vm

package {
   
   mathJaxContainer[14]}{
   
   moduleName}.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import {
   
   mathJaxContainer[15]}{
   
   moduleName}.domain.entity.${
   
   upperClassName};
import com.didiplus.common.web.domain.PageDomain;



/**
 * @author ${author}
 * @date ${datetime}
 *
 * @description ${comment}
 */
public interface I{
   
   mathJaxContainer[16]}{
   
   upperClassName}Entity> {
   
   


    /**
    * 分页查询
    * @param pageDomain
    * @return
    */
    IPage<${
   
   upperClassName}Entity> page(PageDomain pageDomain);

}

serviceImpl.java.vm

package {
   
   mathJaxContainer[17]}{
   
   moduleName}.service.impl;

import com.didiplus.common.web.domain.PageDomain;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import {
   
   mathJaxContainer[18]}{
   
   moduleName}.domain.entity.${
   
   upperClassName}Entity;
import {
   
   mathJaxContainer[19]}{
   
   moduleName}.mapper.${
   
   upperClassName}Mapper;
import {
   
   mathJaxContainer[20]}{
   
   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 {
   
   mathJaxContainer[21]}{
   
   upperClassName}Mapper, {
   
   mathJaxContainer[22]}{
   
   upperClassName}Service {
   
   


        @Resource
        {
   
   mathJaxContainer[23]}{
   
   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 {
   
   mathJaxContainer[24]}{
   
   moduleName}.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import {
   
   mathJaxContainer[25]}{
   
   moduleName}.domain.entity.${
   
   upperClassName}Entity;
import {
   
   mathJaxContainer[26]}{
   
   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{
   
   mathJaxContainer[28]}{
   
   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 {
   
   mathJaxContainer[32]}{
   
   lowerClassName}Entity) {
   
   
        return  {
   
   mathJaxContainer[33]}{
   
   lowerClassName}Entity)? "添加成功":"添加失败";

    }

    /**
     * 修改${comment}
     * @param ${lowerClassName}Entity ${comment}
     * @return Result
     */
    @ApiOperation(value = "修改${comment}", notes = "修改${comment}")
    @PutMapping
    public String updateById(@Validated(ValidGroup.Crud.Update.class)  @RequestBody {
   
   mathJaxContainer[36]}{
   
   lowerClassName}Entity) {
   
   
        return  {
   
   mathJaxContainer[37]}{
   
   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();


    }

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

目录
相关文章
|
6月前
|
Java 测试技术 数据库连接
【MyBatisPlus】MyBatisPlus 整合开发
【1月更文挑战第19天】【MyBatisPlus】MyBatisPlus 整合开发
|
1月前
|
前端开发 Java 数据库连接
表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
本文是一份全面的表白墙/留言墙项目教程,使用SpringBoot + MyBatis技术栈和MySQL数据库开发,涵盖了项目前后端开发、数据库配置、代码实现和运行的详细步骤。
45 0
表白墙/留言墙 —— 中级SpringBoot项目,MyBatis技术栈MySQL数据库开发,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学
|
2月前
|
Java 数据库连接 数据格式
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
IOC/DI配置管理DruidDataSource和properties、核心容器的创建、获取bean的方式、spring注解开发、注解开发管理第三方bean、Spring整合Mybatis和Junit
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
|
3月前
|
SQL Java 数据库连接
Spring Boot联手MyBatis,打造开发利器:从入门到精通,实战教程带你飞越编程高峰!
【8月更文挑战第29天】Spring Boot与MyBatis分别是Java快速开发和持久层框架的优秀代表。本文通过整合Spring Boot与MyBatis,展示了如何在项目中添加相关依赖、配置数据源及MyBatis,并通过实战示例介绍了实体类、Mapper接口及Controller的创建过程。通过本文,你将学会如何利用这两款工具提高开发效率,实现数据的增删查改等复杂操作,为实际项目开发提供有力支持。
178 0
|
3月前
|
SQL Java 数据库连接
后端框架的学习----mybatis框架(7、使用注解开发)
这篇文章讲述了如何使用MyBatis框架的注解方式进行开发,包括在接口上使用注解定义SQL语句,并通过动态代理实现对数据库的增删改查操作,同时强调了接口需要在核心配置文件中注册绑定。
|
5月前
|
SQL XML Java
后端数据库开发JDBC编程Mybatis之用基于XML文件的方式映射SQL语句实操
后端数据库开发JDBC编程Mybatis之用基于XML文件的方式映射SQL语句实操
72 3
|
5月前
|
Java 数据库连接 API
后端开发之用Mybatis简化JDBC的开发快速入门2024及数据库连接池技术和lombok工具详解
后端开发之用Mybatis简化JDBC的开发快速入门2024及数据库连接池技术和lombok工具详解
63 3
|
5月前
|
SQL Java 数据库连接
2万字实操案例之在Springboot框架下基于注解用Mybatis开发实现基础操作MySQL之预编译SQL主键返回增删改查
2万字实操案例之在Springboot框架下基于注解用Mybatis开发实现基础操作MySQL之预编译SQL主键返回增删改查
73 2
|
5月前
|
SQL Java 数据库连接
Mybatis如何使用mapper代理开发
Mybatis如何使用mapper代理开发
|
5月前
|
存储 Java 数据库连接
SSMP整合案例第三步 业务层service开发及基于Mybatis的接口功能拓展
SSMP整合案例第三步 业务层service开发及基于Mybatis的接口功能拓展
37 0