基于mybatis-plus-generator實(shí)現(xiàn)代碼自動(dòng)生成器
1.引入依賴
<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提高高度封裝好的代碼生成器模塊,只需要簡單的幾行代碼就能實(shí)現(xiàn)。同時(shí)也可以根據(jù)自己的需求靈活的通過模板話的方式生成代碼。下面我們分別通過這兩種方式來了解一些。
2.簡單的代碼生成
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") // 設(shè)置作者 .enableSwagger() //開啟 swagger 模式 .outputDir("D://autocode");// 指定輸出目錄 }) .packageConfig(builder -> { builder.parent("com.didiplus.models") // 設(shè)置父包名 .moduleName("sys") // 設(shè)置父包模塊名 .pathInfo(Collections.singletonMap(OutputFile.xml,"D://autocode/xml")); }) .strategyConfig(builder -> { builder.addInclude("sys_dict_data") // 設(shè)置需要生成的表名 .addTablePrefix("t_","c_") ; // 設(shè)置過濾表前綴 }) // .templateEngine(new FreemarkerTemplateEngine()) 使用Freemarker引擎模板,默認(rèn)的是Velocity引擎模板 .execute(); } }
運(yùn)行以上代碼,會(huì)自動(dòng)的在D盤生成代碼,但是,生成的代碼只是最基本的模板。
以上生成的代碼都是基于MybatisPlus代碼生成默認(rèn)模板去生成的。適合絕大多數(shù)場景。我們也可以根據(jù)自己的模板文件去生成代碼的。
3.自定義模板生成代碼
3.1實(shí)現(xiàn)思路
從數(shù)據(jù)庫中讀取表的相關(guān)信息和表的相關(guān)字段
定義相對于的模板文件
組裝模板屬性
3.2定義代碼生成常量
這些常量主要用戶后期在組裝模板時(shí),把數(shù)據(jù)庫類型轉(zhuǎn)換成Java數(shù)據(jù)類型需要用到的。
package com.didiplus.constant; /** * Author: didiplus * Email: 972479352@qq.com * CreateTime: 2022/5/6 * Desc: 碼 生 成 通 用 常 量 */ public class GenerateConstant { /** * 數(shù)據(jù)庫字符串類型 */ public static final String[] COLUMN_TYPE_STR = {"char", "varchar", "nvarchar", "varchar2", "tinytext", "text", "mediumtext", "longtext"}; /** * 數(shù)據(jù)庫時(shí)間類型 */ public static final String[] COLUMN_TYPE_TIME = {"datetime", "time", "date", "timestamp"}; /** * 數(shù)據(jù)庫數(shù)字類型 */ public static final String[] COLUMN_TYPE_NUMBER = {"tinyint", "smallint", "mediumint", "int", "number", "integer", "bit"}; /** * 數(shù)據(jù)庫bigint類型 */ public static final String[] COLUMN_TYPE_BIGINT = {"bigint"}; /** * 數(shù)據(jù)庫float類型 */ public static final String[] COLUMN_TYPE_FLOAT = {"float"}; /** * 數(shù)據(jù)庫double類型 */ public static final String[] COLUMN_TYPE_DOUBLE = {"double"}; /** * 數(shù)據(jù)庫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"; /** * 浮點(diǎn)型 */ public static final String TYPE_DOUBLE = "Double"; /** * 高精度計(jì)算類型 */ public static final String TYPE_BIGDECIMAL = "BigDecimal"; /** * 時(shí)間類型 */ public static final String TYPE_DATE = "Date"; }
3.3全局配置
/** * 全局配置 */ private GlobalConfig.Builder globalConfig() { String projectPath = System.getProperty("user.dir"); return new GlobalConfig.Builder() .fileOverride() // 覆蓋已生成文件 .disableOpenDir() // 禁止打開輸出目錄 默認(rèn)值:true .author("didiplus") //作者名 .outputDir(projectPath+"/src/main/resources/autocode") // 指定輸出目錄 .enableSwagger(); // 開啟 swagger 模式 默認(rèn)值:false }
3.4定義生成代碼模板的路徑
/** * 模板配置 */ 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"); }
以上的函數(shù)是聲明代碼生成根據(jù)這些模板去生成對應(yīng)的模板。
3.5定義各文件生成存儲(chǔ)路徑
/** * 包配置 */ 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"); }
3.6數(shù)據(jù)源配置
/** * 數(shù)據(jù)源配置 */ 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();
3.7配置策略
/** * 策略配置 */ private StrategyConfig.Builder strategyConfig() { return new StrategyConfig.Builder() .addInclude(tableName); }
3.8組裝模板屬性
/** * 注入配置 */ 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 數(shù)據(jù)源 * @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'"; // 利用現(xiàn)有的dataSourceConfig來獲取數(shù)據(jù)庫連接,查詢表字段及備注等信息 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<>(); // 列名字、數(shù)據(jù)類型、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執(zhí)行出錯(cuò)"); e.printStackTrace(); } map.put("columns",columns); map.put("datetime", DateUtil.now()); map.put("packageName", packageName); map.put("moduleName", moduleName); } /** * 數(shù)據(jù)庫類型轉(zhuǎn)換為java類型 * * @param columnType 數(shù)據(jù)庫類型 * @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; }
3.9定義對應(yīng)的模板文件
在項(xiàng)目的資源文件夾templats
中創(chuàng)建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}實(shí)體類) */ @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)? "刪除成功":"刪除失敗"; } }
3.10定義啟動(dòng)類
執(zhí)行以上函數(shù)就可以自動(dòng)生成代碼了,如下圖:
目前代碼自動(dòng)生成器只是一個(gè)腳本方式運(yùn)行,后續(xù)我們會(huì)把它集成到頁面上,通過圖形界面的方式去操作。
以上就是基于mybatis-plus-generator實(shí)現(xiàn)代碼自動(dòng)生成器的詳細(xì)內(nèi)容,更多關(guān)于mybatis-plus-generator代碼生成的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java實(shí)現(xiàn)五子棋游戲(控制臺(tái)版)
這篇文章主要為大家詳細(xì)介紹了Java控制臺(tái)版實(shí)現(xiàn)五子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10Eclipse遠(yuǎn)程debug的步驟與注意事項(xiàng)
今天小編就為大家分享一篇關(guān)于Eclipse遠(yuǎn)程debug的步驟與注意事項(xiàng),小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-03-03Java并發(fā)volatile可見性的驗(yàn)證實(shí)現(xiàn)
這篇文章主要介紹了Java并發(fā)volatile可見性的驗(yàn)證實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05Java中CompletableFuture?的詳細(xì)介紹
這篇文章主要介紹了Java中的CompletableFuture,通過創(chuàng)建?CompletableFuture?的對象的工廠方法展開詳細(xì)的內(nèi)容介紹,需要的小伙伴可以參考一下2022-05-05Spring Cloud Alibaba Nacos Config進(jìn)階使用
這篇文章主要介紹了Spring Cloud Alibaba Nacos Config進(jìn)階使用,文中使用企業(yè)案例,圖文并茂的展示了Nacos Config的使用,感興趣的小伙伴可以看一看2021-08-08MybatisPlus 主鍵策略的幾種實(shí)現(xiàn)方法
MybatisPlus-Plus支持多種主鍵生成策略,可以通過@TableId注解的type屬性配置,主要策略包括AUTO、INPUT、ASSING_ID、ASSING_UUID和NONE,每種策略適用于不同的場景,下面就來介紹一下2024-10-10SpringBoot結(jié)合Redis哨兵模式的實(shí)現(xiàn)示例
這篇文章主要介紹了SpringBoot結(jié)合Redis哨兵模式的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04spring學(xué)習(xí)之@SessionAttributes實(shí)例解析
這篇文章主要介紹了spring學(xué)習(xí)之@SessionAttributes實(shí)例解析,分享了相關(guān)代碼示例,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-02-02Java通過Process類Runtime.getRuntime().exec()執(zhí)行bat腳本程序
用Java編寫應(yīng)用時(shí),有時(shí)需要在程序中調(diào)用另一個(gè)現(xiàn)成的可執(zhí)行程序或系統(tǒng)命令,這篇文章主要給大家介紹了關(guān)于Java如何通過Process類Runtime.getRuntime().exec()執(zhí)行bat腳本程序的相關(guān)資料,需要的朋友可以參考下2024-01-01