SpringBoot+MyBatis-Plus+Velocity实现代码自动生成
目录
- 1. 前提条件
- 2. 代码生成器设计
- 2.1 配置代码生成器
- 2.2 Velocity 模板
- 3. 运行生成代码
- 4. 测试接口
- 5. 总结
1. 前提条件
开发环境:
- Spring Boot 2.x
- MyBATis-Plus
- Lombok
- Swagger & Knife4j
- Velocity 模板引擎
- 数据库(mysql)
所需依赖:
在 pom.XML
中加入以下依赖:
<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. 代码生成器设计
接下来我们创建一个 代码生成器,该生成器能够通过查询数据库的表信息并生成相应的代码。
2.1 配置代码生成器
在 CodeGenerator.Java
中,编写生成代码的逻辑。主要是从数据库读取表结构信息,并通过 Velocity 模板生成对应的实体类、Mapper、Service、Controller 等代码。
package com.example.demo.generator; import java.sql.*; import java.util.*; public class CodeGenerator { public static void main(String[] args) { // 配置数据库连接 String url = "jdbc:mysql://localhost:3306/your_database"; String username = "root"; String password = "password"; String database = "your_database"; String tableName = "your_table"; // 获取表信息并生成代码 Map<Sphptring, 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)) { // 查询表注释 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")); } } // 查询字段信息 String columnQuery = "SELECT column_name, column_type, column_comment FROM information_schema.columns WHERE table_schema = ? AND table_name = ?"; Lis编程t<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"))); // 转换为 Java 变量名 columnInfo.put("javaType", sqlTypephpToJavaType(rs.getString("column_type"))); // 转换为 Java 类型 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"); // 设置 Velocity 配置 VelocityEngine velocityEngine = new VelocityEngine(); velocityEngine.init(); // 配置模板目录 String templateDir = "path/to/your/templates"; // 模板文件的路径 // 设置输出目录 String outputDir = "path/to/output"; // 输出的代码文件夹路径 // 创建 Velocity 上下文 VelocityContext context = new VelocityContext(); context.put("package", "com.example"); // 设置包路径 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); // 创建文件输出流 try (FileWriter writer = new FileWriter(outputFilePath)) { // 将上下文数据渲染到模板中 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} 实体") 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("删除 ${tablejavascriptComment}") public boolean delete(@PathVariable Long id) { return service.removeById(id); } }
3. 运行生成代码
- 启动 Spring Boot 项目,配置好数据库连接。
- 运行
CodeGenerator.java
,自动从数据库中读取表信息,并生成相应的代码。 - 查看生成的代码:
- 实体类:包含数据库表字段的实体类代码。
- Mapper、Service、ServiceImpl、Controller:自动生成增删改查接口和实现。
4. 测试接口
启动项目后,使用 Swagger UI 进行接口测试。访问 http://localhost:8080/doc.html
可以看到自动生成的接口文档,通过 Swagger 的 UI 直接进行增删改查操作。
5. 总结
通过本教程,我们利用 Spring Boot、MyBatis-Plus 和 Velocity 模板引擎 实现了一个自动化的代码生成器,能够根据数据库表结构自动生成增删改查操作的代码,并且集成了 Lombok、Swagger 和 Knife4j,极大地提高了开发效率。
到此这篇关于SpringBoot+MyBatis-Plus+Velocity实现代码自动生成的文章就介绍到这了,更多相关SpringBoot MyBatisPlus 代码自动生成内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论