package com.ruoyi; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.generator.FastAutoGenerator; import com.baomidou.mybatisplus.generator.config.OutputFile; import com.baomidou.mybatisplus.generator.config.rules.DateType; import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine; import com.baomidou.mybatisplus.generator.fill.Column; import org.springframework.boot.autoconfigure.SpringBootApplication; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Map; /** * MyBatis-Plus 代码生成器 * 功能:根据数据库表结构自动生成Entity、Mapper、Service、Controller等代码 * 修复:解决Freemarker模板中generateService变量缺失的问题 */ @SpringBootApplication public class PlusCodeGenerator { // 数据库配置 private static final String DB_URL = "jdbc:postgresql://localhost:5432/ruoyi-java"; private static final String DB_USERNAME = "postgres"; private static final String DB_PASSWORD = "root"; // 项目基础配置 private static final String BASE_PACKAGE = "com.ruoyi"; private static final String MODULE_NAME = "basic"; // 模块名 public static void main(String[] args) { String projectPath = System.getProperty("user.dir"); // 获取项目根路径 String path = "ruoyi-system"; // 模块名称 String table = "province,city,district"; // 表名,多个表逗号隔开 // 代码输出路径配置 String outputBasePath = Paths.get(projectPath, path, "src", "main", "java").toString(); String outputResourcePath = Paths.get(projectPath, path, "src", "main", "resources", "mapper").toString(); // 代码生成核心配置 FastAutoGenerator.create(DB_URL, DB_USERNAME, DB_PASSWORD) .globalConfig(builder -> { builder.author("chenhj") // 作者信息 .outputDir(outputBasePath) // 代码输出目录 .dateType(DateType.ONLY_DATE) // 日期类型 .commentDate("yyyy-MM-dd") // 注释日期格式 .disableOpenDir(); // 禁止自动打开输出目录 }) .packageConfig(builder -> { builder.parent(BASE_PACKAGE) // 基础包名 .moduleName(MODULE_NAME) // 模块名(根据具体修改) .entity("entity") // Entity包名 .mapper("mapper") // Mapper包名 .service("service") // Service包名 .serviceImpl("service.impl") // Service实现类包名 .controller("controller") // Controller包名 .pathInfo(Collections.singletonMap( OutputFile.xml, outputResourcePath // Mapper XML输出路径 )); }) .strategyConfig(builder -> { builder.addInclude(table) // 要生成的表名 .addTablePrefix("t_", "sys_") // 过滤表前缀 // 实体类配置 .entityBuilder() .superClass("com.ruoyi.common.core.domain.BaseEntity") // 继承基类 .addSuperEntityColumns("create_by", "create_time", "update_by", "update_time") // 排除基类字段 .enableLombok() // 启用Lombok .naming(NamingStrategy.underline_to_camel) // 表名转驼峰 .columnNaming(NamingStrategy.underline_to_camel) // 列名转驼峰 .enableFileOverride() // 允许覆盖文件 .logicDeleteColumnName("deleted") // 逻辑删除字段 .addTableFills( // 自动填充配置 new Column("create_by", FieldFill.INSERT), // 创建人,插入时填充 new Column("update_by", FieldFill.INSERT_UPDATE), // 更新人,插入和更新时填充 new Column("create_time", FieldFill.INSERT), // 创建时间,插入时填充 new Column("update_time", FieldFill.INSERT_UPDATE) // 更新时间,插入和更新时填充 ) .idType(IdType.AUTO) // 主键策略 .enableTableFieldAnnotation() // 启用字段注解 // 控制器配置 .controllerBuilder() .enableFileOverride() // 允许覆盖 .enableRestStyle() // 生成RESTful风格控制器 // Service配置 .serviceBuilder() .formatServiceFileName("%sService") // Service接口命名格式 .enableFileOverride() // 允许覆盖 .formatServiceImplFileName("%sServiceImpl") // Service实现类命名格式 .enableFileOverride() // 允许覆盖 // Mapper配置 .mapperBuilder() .enableFileOverride() // 允许覆盖 .enableMapperAnnotation() // 启用@Mapper注解 .enableBaseResultMap() // 启用基础ResultMap .enableBaseColumnList() // 启用基础ColumnList .formatMapperFileName("%sMapper") // Mapper接口命名格式 .formatXmlFileName("%sMapper") // Mapper XML命名格式 .enableFileOverride(); // 允许覆盖 }) // 配置自定义模板 .templateConfig(builder -> { builder .entity("/templates/entity.java") // 实体类模板 .xml("/templates/mapper.xml") // Mapper XML模板 .controller("/templates/controller.java") // 控制器模板 .serviceImpl("/templates/serviceImpl.java"); // Service实现类模板 }) // 注入模板变量 .injectionConfig(builder -> { Map customMap = new HashMap<>(); customMap.put("superEntityColumns", Arrays.asList( "create_by", "create_time", "update_by", "update_time" )); // 基类字段 customMap.put("idType", "AUTO"); // 主键类型 customMap.put("superEntityClass", "com.ruoyi.common.core.domain.BaseEntity"); // 基类全路径 customMap.put("author", "ruoyi"); // 作者信息 customMap.put("packageName", BASE_PACKAGE + "." + MODULE_NAME); // 包名 customMap.put("tableName", table); // 表名 // 新增:解决Freemarker模板中generateService变量缺失的问题 // 控制Service实现类是否实现Service接口 boolean generateService = true; customMap.put("generateService", generateService); builder.customMap(customMap); }) .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker模板引擎 .execute(); // 执行代码生成 // 后处理:修复实体类的完全限定名问题 try { Path entityPath = Paths.get(outputBasePath, "com/ruoyi/basic/entity/Test.java"); if (Files.exists(entityPath)) { String content = Files.readString(entityPath); content = content.replace( "extends com.ruoyi.common.core.domain.BaseEntity", "extends BaseEntity" ); // 简化基类引用 Files.writeString(entityPath, content); } } catch (IOException e) { System.err.println("⚠️ 修复实体类失败: " + e.getMessage()); } System.out.println("✅ 代码生成完成!文件已输出到:" + outputBasePath); } }