SpringBoot+MyBatis-Plus+Velocity實(shí)現(xiàn)代碼自動(dòng)生成
1. 前提條件
開(kāi)發(fā)環(huán)境:
- Spring Boot 2.x
- MyBatis-Plus
- Lombok
- Swagger & Knife4j
- Velocity 模板引擎
- 數(shù)據(jù)庫(kù)(MySQL)
所需依賴(lài):
在 pom.xml 中加入以下依賴(lài):
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis-Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
<!-- Swagger -->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.6.0</version>
</dependency>
<!-- Knife4j -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-springdoc-ui</artifactId>
<version>2.0.6</version>
</dependency>
<!-- Velocity -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
</dependencies>
2. 代碼生成器設(shè)計(jì)
接下來(lái)我們創(chuàng)建一個(gè) 代碼生成器,該生成器能夠通過(guò)查詢(xún)數(shù)據(jù)庫(kù)的表信息并生成相應(yīng)的代碼。
2.1 配置代碼生成器
在 CodeGenerator.java 中,編寫(xiě)生成代碼的邏輯。主要是從數(shù)據(jù)庫(kù)讀取表結(jié)構(gòu)信息,并通過(guò) Velocity 模板生成對(duì)應(yīng)的實(shí)體類(lèi)、Mapper、Service、Controller 等代碼。
package com.example.demo.generator;
import java.sql.*;
import java.util.*;
public class CodeGenerator {
public static void main(String[] args) {
// 配置數(shù)據(jù)庫(kù)連接
String url = "jdbc:mysql://localhost:3306/your_database";
String username = "root";
String password = "password";
String database = "your_database";
String tableName = "your_table";
// 獲取表信息并生成代碼
Map<String, Object> tableInfo = getTableInfo(url, username, password, database, tableName);
generateCode(tableInfo);
}
public static Map<String, Object> getTableInfo(String url, String username, String password, String database, String tableName) {
Map<String, Object> map = new HashMap<>();
try (Connection conn = DriverManager.getConnection(url, username, password)) {
// 查詢(xún)表注釋
String tableQuery = "SELECT table_comment FROM information_schema.tables WHERE table_schema = ? AND table_name = ?";
try (PreparedStatement ps = conn.prepareStatement(tableQuery)) {
ps.setString(1, database);
ps.setString(2, tableName);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
map.put("tableComment", rs.getString("table_comment"));
}
}
// 查詢(xún)字段信息
String columnQuery = "SELECT column_name, column_type, column_comment FROM information_schema.columns WHERE table_schema = ? AND table_name = ?";
List<Map<String, String>> columns = new ArrayList<>();
try (PreparedStatement ps = conn.prepareStatement(columnQuery)) {
ps.setString(1, database);
ps.setString(2, tableName);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
Map<String, String> columnInfo = new HashMap<>();
columnInfo.put("columnName", rs.getString("column_name"));
columnInfo.put("javaName", toCamelCase(rs.getString("column_name"))); // 轉(zhuǎn)換為 Java 變量名
columnInfo.put("javaType", sqlTypeToJavaType(rs.getString("column_type"))); // 轉(zhuǎn)換為 Java 類(lèi)型
columnInfo.put("comment", rs.getString("column_comment"));
columns.add(columnInfo);
}
}
map.put("columns", columns);
map.put("tableName", tableName);
map.put("entityName", toCamelCase(tableName));
} catch (SQLException e) {
e.printStackTrace();
}
return map;
}
private static String sqlTypeToJavaType(String sqlType) {
sqlType = sqlType.toLowerCase();
if (sqlType.contains("int")) {
return "Integer";
} else if (sqlType.contains("bigint")) {
return "Long";
} else if (sqlType.contains("char") || sqlType.contains("text") || sqlType.contains("varchar")) {
return "String";
} else if (sqlType.contains("datetime") || sqlType.contains("timestamp")) {
return "LocalDateTime";
} else if (sqlType.contains("date")) {
return "LocalDate";
} else if (sqlType.contains("decimal") || sqlType.contains("double")) {
return "BigDecimal";
} else {
return "String";
}
}
private static String toCamelCase(String name) {
StringBuilder result = new StringBuilder();
String[] parts = name.split("_");
for (int i = 0; i < parts.length; i++) {
if (i == 0) {
result.append(parts[i].toLowerCase());
} else {
result.append(Character.toUpperCase(parts[i].charAt(0))).append(parts[i].substring(1).toLowerCase());
}
}
return result.toString();
}
private static void generateCode(Map<String, Object> tableInfo) {
// 讀取表信息
String entityName = (String) tableInfo.get("entityName");
String tableName = (String) tableInfo.get("tableName");
String tableComment = (String) tableInfo.get("tableComment");
List<Map<String, String>> columns = (List<Map<String, String>>) tableInfo.get("columns");
// 設(shè)置 Velocity 配置
VelocityEngine velocityEngine = new VelocityEngine();
velocityEngine.init();
// 配置模板目錄
String templateDir = "path/to/your/templates"; // 模板文件的路徑
// 設(shè)置輸出目錄
String outputDir = "path/to/output"; // 輸出的代碼文件夾路徑
// 創(chuàng)建 Velocity 上下文
VelocityContext context = new VelocityContext();
context.put("package", "com.example"); // 設(shè)置包路徑
context.put("entityName", entityName);
context.put("tableName", tableName);
context.put("tableComment", tableComment);
context.put("columns", columns);
// 生成 Entity 文件
generateFile(velocityEngine, context, templateDir, "entity.vm", outputDir + "/entity/" + entityName + ".java");
// 生成 Mapper 文件
generateFile(velocityEngine, context, templateDir, "mapper.vm", outputDir + "/mapper/" + entityName + "Mapper.java");
// 生成 Service 接口文件
generateFile(velocityEngine, context, templateDir, "service.vm", outputDir + "/service/" + entityName + "Service.java");
// 生成 ServiceImpl 文件
generateFile(velocityEngine, context, templateDir, "serviceImpl.vm", outputDir + "/service/impl/" + entityName + "ServiceImpl.java");
// 生成 Controller 文件
generateFile(velocityEngine, context, templateDir, "controller.vm", outputDir + "/controller/" + entityName + "Controller.java");
}
private static void generateFile(VelocityEngine velocityEngine, VelocityContext context, String templateDir, String templateName, String outputFilePath) {
// 獲取模板
Template template = velocityEngine.getTemplate(templateDir + "/" + templateName);
// 創(chuàng)建文件輸出流
try (FileWriter writer = new FileWriter(outputFilePath)) {
// 將上下文數(shù)據(jù)渲染到模板中
template.merge(context, writer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.2 Velocity 模板
Entity 模板(entity.vm)
package ${package.Entity};
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.math.BigDecimal;
@Data
@TableName("${tableName}")
@ApiModel(value = "${entityName} 實(shí)體")
public class ${entityName} implements Serializable {
private static final long serialVersionUID = 1L;
@TableId
@ApiModelProperty("主鍵ID")
private Long id;
#foreach ($column in $columns)
@ApiModelProperty("${column.comment}")
private ${column.javaType} ${column.javaName};
#end
}
Mapper 模板(mapper.vm)
package ${package.Mapper};
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import ${package.Entity}.${entityName};
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ${entityName}Mapper extends BaseMapper<${entityName}> {
}
Service 模板(service.vm)
package ${package.Service};
import ${package.Entity}.${entityName};
import com.baomidou.mybatisplus.extension.service.IService;
public interface ${entityName}Service extends IService<${entityName}> {
}
ServiceImpl 模板(serviceImpl.vm)
package ${package.ServiceImpl};
import ${package.Entity}.${entityName};
import ${package.Mapper}.${entityName}Mapper;
import ${package.Service}.${entityName}Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service
public class ${entityName}ServiceImpl extends ServiceImpl<${entityName}Mapper, ${entityName}> implements ${entityName}Service {
}
Controller 模板(controller.vm)
package ${package.Controller};
import ${package.Entity}.${entityName};
import ${package.Service}.${entityName}Service;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import javax.annotation.Resource;
import java.util.List;
@RestController
@RequestMapping("/${tableName}")
@Api(tags = "${tableComment}")
public class ${entityName}Controller {
@Resource
private ${entityName}Service service;
@GetMapping("/list")
@ApiOperation("獲取所有 ${tableComment}")
public List<${entityName}> list() {
return service.list();
}
@PostMapping("/add")
@ApiOperation("新增 ${tableComment}")
public boolean add(@RequestBody ${entityName} entity) {
return service.save(entity);
}
@PutMapping("/update")
@ApiOperation("更新 ${tableComment}")
public boolean update(@RequestBody ${entityName} entity) {
return service.updateById(entity);
}
@DeleteMapping("/delete/{id}")
@ApiOperation("刪除 ${tableComment}")
public boolean delete(@PathVariable Long id) {
return service.removeById(id);
}
}
3. 運(yùn)行生成代碼
- 啟動(dòng) Spring Boot 項(xiàng)目,配置好數(shù)據(jù)庫(kù)連接。
- 運(yùn)行
CodeGenerator.java,自動(dòng)從數(shù)據(jù)庫(kù)中讀取表信息,并生成相應(yīng)的代碼。 - 查看生成的代碼:
- 實(shí)體類(lèi):包含數(shù)據(jù)庫(kù)表字段的實(shí)體類(lèi)代碼。
- Mapper、Service、ServiceImpl、Controller:自動(dòng)生成增刪改查接口和實(shí)現(xiàn)。
4. 測(cè)試接口
啟動(dòng)項(xiàng)目后,使用 Swagger UI 進(jìn)行接口測(cè)試。訪問(wèn) http://localhost:8080/doc.html 可以看到自動(dòng)生成的接口文檔,通過(guò) Swagger 的 UI 直接進(jìn)行增刪改查操作。
5. 總結(jié)
通過(guò)本教程,我們利用 Spring Boot、MyBatis-Plus 和 Velocity 模板引擎 實(shí)現(xiàn)了一個(gè)自動(dòng)化的代碼生成器,能夠根據(jù)數(shù)據(jù)庫(kù)表結(jié)構(gòu)自動(dòng)生成增刪改查操作的代碼,并且集成了 Lombok、Swagger 和 Knife4j,極大地提高了開(kāi)發(fā)效率。
到此這篇關(guān)于SpringBoot+MyBatis-Plus+Velocity實(shí)現(xiàn)代碼自動(dòng)生成的文章就介紹到這了,更多相關(guān)SpringBoot MyBatisPlus 代碼自動(dòng)生成內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot如何使用MyBatisPlus逆向工程自動(dòng)生成代碼
- SpringBoot集成Mybatis-plus并實(shí)現(xiàn)自動(dòng)生成相關(guān)文件的示例代碼
- Springboot Mybatis Plus自動(dòng)生成工具類(lèi)詳解代碼
- SpringBoot項(xiàng)目使用mybatis-plus逆向自動(dòng)生成全套代碼
- SpringBoot整合Mybatis Generator自動(dòng)生成代碼
- SpringBoot根據(jù)目錄結(jié)構(gòu)自動(dòng)生成路由前綴的實(shí)現(xiàn)代碼
- springboot整合freemarker代碼自動(dòng)生成器
- SpringBoot整合screw實(shí)現(xiàn)數(shù)據(jù)庫(kù)文檔自動(dòng)生成的示例代碼
- springboot 通過(guò)代碼自動(dòng)生成pid的方法
相關(guān)文章
elasticsearch的靈魂唯一master選舉機(jī)制原理分析
這篇文章主要為大家介紹了elasticsearch的靈魂唯一master選舉機(jī)制原理分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04
java線(xiàn)程中synchronized和Lock區(qū)別及介紹
這篇文章主要為大家介紹了java線(xiàn)程中synchronized和Lock區(qū)別及介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06
Spring?Boot整合Kafka+SSE實(shí)現(xiàn)實(shí)時(shí)數(shù)據(jù)展示
本文主要介紹了Spring?Boot整合Kafka+SSE實(shí)現(xiàn)實(shí)時(shí)數(shù)據(jù)展示2024-06-06
Java高并發(fā)編程之CAS實(shí)現(xiàn)無(wú)鎖隊(duì)列代碼實(shí)例
這篇文章主要介紹了Java高并發(fā)編程之CAS實(shí)現(xiàn)無(wú)鎖隊(duì)列代碼實(shí)例,在多線(xiàn)程操作中,我們通常會(huì)添加鎖來(lái)保證線(xiàn)程的安全,那么這樣勢(shì)必會(huì)影響程序的性能,那么為了解決這一問(wèn)題,于是就有了在無(wú)鎖操作的情況下依然能夠保證線(xiàn)程的安全,需要的朋友可以參考下2023-12-12
java實(shí)現(xiàn)新浪微博Oauth接口發(fā)送圖片和文字的方法
這篇文章主要介紹了java實(shí)現(xiàn)新浪微博Oauth接口發(fā)送圖片和文字的方法,涉及java調(diào)用新浪微博Oauth接口的使用技巧,具有一定參考接借鑒價(jià)值,需要的朋友可以參考下2015-07-07
Java實(shí)現(xiàn)支付對(duì)接常用加密方式的示例代碼
這篇文章主要為大家詳細(xì)介紹了Java如何實(shí)現(xiàn)支付對(duì)接時(shí)常用加密方式,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Java有一點(diǎn)幫助,需要的可以參考一下2023-02-02
Java調(diào)用Python腳本傳遞數(shù)據(jù)并返回計(jì)算結(jié)果
實(shí)際工程項(xiàng)目中可能會(huì)用到Java和python兩種語(yǔ)言結(jié)合進(jìn)行,這樣就會(huì)涉及到一個(gè)問(wèn)題,Java如何調(diào)用Python腳本,感興趣的可以了解一下2021-05-05
scala 隱式轉(zhuǎn)換與隱式參數(shù)的使用方法
這篇文章主要介紹了scala 隱式轉(zhuǎn)換與隱式參數(shù)的使用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11

