1. 程式人生 > 其它 >專門為小白準備的入門級mybatis-plus-generator程式碼自動生成器,提高開發效率。值得收藏

專門為小白準備的入門級mybatis-plus-generator程式碼自動生成器,提高開發效率。值得收藏

引入依賴

        <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: [email protected]
 * 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: [email protected]
 * 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();


    }

執行以上函式就可以自動生成程式碼了,如下圖:
目前程式碼自動生成器只是一個指令碼方式執行,後續我們會把它整合到頁面上,通過圖形介面的方式去操作。好了今天就分享到這裡了,有什麼問題歡迎留意。更多關注公眾號“攻城獅成長日記”。