ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SpringBoot集成MyBatis-Plus自动代码生成器,告别手写CRUD

SpringBoot集成MyBatis-Plus自动代码生成器,告别手写CRUD 如果你是一个天天写CRUD的Java后端大概早就受够了这套重复劳动数据库加一张表就要新建Entity、写Mapper接口、写Service接口、写ServiceImpl实现类、再写Controller每个文件都是差不多的模板代码复制粘贴改个类名和字段一不留神还会漏个注解。SpringBoot使用Mybatis-Plus的自动代码生成器就是专门解决这个问题的东西。它读一遍数据库表结构直接把上述一套代码全部生成好甚至还能顺带处理好逻辑删除、乐观锁、自动填充这些常用功能。这篇文章我会用一个可以从零跑通的完整案例把这个生成器的原理、配置、实操过程和踩坑记录都讲明白。无论你是刚接触MyBatis-Plus的新手还是已经用了很久但只手动写代码的老手看完都能把生成器纳入自己的日常开发流程省下大量重复劳动。1. 先说清楚这个生成器到底帮你干了什么1.1 从“复制粘贴”到“点一下生成”在我接触MyBatis-Plus生成器之前业务系统里每增加一张表流程基本是这样的先在数据库里建表然后在IDE里对照字段类型手动创建Entity注意从int映射Integer、从varchar映射Stringdatetime别忘了用LocalDateTime接着写Mapper接口继承BaseMapper泛型里填对实体类再写Service接口声明几个常用的CRUD方法然后是ServiceImpl实现类继承MyBatis-Plus的ServiceImpl最后写Controller加RestController注解RequestMapping路径要和表名对上。这套流程我大概花了三年时间重复。每次大概十五到二十分钟不算太久但架不住表多而且多表之间的代码风格还容易不一致。有的人习惯在Mapper上加Mapper注解有的人不写交接入职新人时还要靠口头约定对齐。MyBatis-Plus的自动代码生成器核心价值就在这里你只需要建好表、配好连接、写好策略它就能一次性把这些东西全部生成风格统一、注解完整、直接可用。用我自己的话说这件事的本质是把“信息从数据库表结构复制到Java类”的过程自动化。表结构本来就包含了足够的信息——表名、字段名、字段类型、注释、主键——生成器把这些信息读取出来根据你配置好的规则转换成Java代码。1.2 它能生成哪几层代码MyBatis-Plus生成器的核心能力是从数据表直接生成一套围绕该表的完整代码主要包括Entity实体类对应表结构每个字段一个属性带TableName、TableId、TableField等注解开启Lombok后还会生成Getter/Setter。Mapper接口继承BaseMapper 自带增删改查方法也可以配置Mapper注解或单独生成XML文件。Service接口继承IService 提供若干业务层通用方法。ServiceImpl实现类继承ServiceImplM,T实现业务接口。Controller控制器类默认生成基于Restful风格的接口方法名和请求路径都可以按你的需求配置。生成的代码不是简单的空壳关键注解和数据源信息都会自动对齐。比如数据库里叫user_name的字段默认会映射成Java的userName并且在Entity上生成TableField(user_name)保证MyBatis-Plus执行SQL时能正确对应。1.3 我的选型理由为什么不是其他生成器Java生态里代码生成器其实不少最经典的当属MyBatis GeneratorMBG。我也用过MBG它确实能生成实体和Mapper但问题也很明显只覆盖到Mapper层Service和Controller还得自己写对MyBatis-Plus特有的逻辑删除、乐观锁、自动填充这些注解支持不好生成的实体用起来总觉得差点意思。还有一类是类似RuoYi脚手架自带的生成代码功能但那是在一个闭环体系里用的拆出来单独适配自己的项目反而麻烦。MyBatis-Plus生成器胜在“贴合MyBatis-Plus体系”。它本身就是为了这个框架服务的生成出来的Entiy、Mapper、ServiceImpl天然就依赖MyBatis-Plus的基类你不需要再手动加那么多模板注解生成完直接启动项目就能跑。再加上整体配置是链式的Java API所见即所得没有复杂的XML模板文件排错和定制都相对直观。尤其是新版FastAutoGenerator出现之后配置过程比旧版AutoGenerator更简洁几步就能跑通这也是我推荐大家直接学新版的原因。2. 环境准备版本和依赖坑从这里开始2.1 SpringBoot版本决定你的依赖坐标在动手之前一定要先搞清楚自己项目的SpringBoot版本尤其是现在SpringBoot 3.x已经普及它和2.x在依赖坐标上差别很大。如果你还在用SpringBoot 2.x也就是JDK 8为主的项目那么依赖坐标是mybatis-plus-boot-starter如果你的项目是SpringBoot 3.x基于JDK 17那么必须换成mybatis-plus-spring-boot3-starter。这两个starter的包名不一样用错了最常见的表现就是启动报错或者找不到SqlSessionFactory相关的类。我个人的建议是新项目直接用SpringBoot 3.x因为生态已经成熟JDK 17也是当前的主流老项目如果只是升级生成器那就保持原版本不动单独把代码生成器作为一个独立的小模块跑就行不必为了生成代码去动整个项目的依赖。2.2 代码生成器依赖清单代码生成器本身并不复杂核心是MyBatis-Plus的generator依赖另外还要引入数据库驱动和模板引擎。我这里用一个独立的Maven模块来演示避免污染主业务的依赖。如果你是直接加到自己的业务模块里建议后面再看第5.5节把生成器代码挪到单独模块中去。以SpringBoot 3.x为例关键的依赖坐标如下dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-spring-boot3-starter/artifactId version3.5.7/version /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-generator/artifactId version3.5.7/version /dependency dependency groupIdorg.freemarker/groupId artifactIdfreemarker/artifactId version2.3.32/version /dependency dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId version8.0.33/version scoperuntime/scope /dependency这里有几个坑需要说明。第一个是版本在较新的MyBatis-Plus版本里mybatis-plus-generator的版本要和starter版本基本一致否则可能出现接口不兼容。第二个是模板引擎MyBatis-Plus默认用的是Velocity如果不额外引入模板引擎依赖它就会使用内置的Velocity处理但你如果指定了FreemarkerTemplateEngine的类就必须有freemarker依赖。第三个是数据库驱动MySQL 8以上的版本用com.mysql.cj.jdbc.Driver驱动driver类名别写错。2.3 准备一张比较有代表性的表生成器的输入是数据库表所以先准备一张覆盖常见字段类型的演示表。我建议表里带上主键、字符串、整数、时间、逻辑删除、乐观锁这些要素。这样你能看到生成器对各种类型的处理效果。这里我建一张简单的用户表名字叫tb_user注意带上了tb_前缀后面用来演示表前缀的去重功能CREATE TABLE tb_user ( id bigint NOT NULL AUTO_INCREMENT COMMENT 主键ID, username varchar(50) NOT NULL COMMENT 用户名, password varchar(128) NOT NULL COMMENT 密码, age int DEFAULT NULL COMMENT 年龄, email varchar(128) DEFAULT NULL COMMENT 邮箱, status tinyint(1) DEFAULT 1 COMMENT 状态0-禁用1-启用, create_time datetime DEFAULT NULL COMMENT 创建时间, update_time datetime DEFAULT NULL COMMENT 更新时间, deleted tinyint(1) DEFAULT 0 COMMENT 逻辑删除0-未删除1-已删除, version int DEFAULT 0 COMMENT 乐观锁版本号, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT用户表;建表时有几件事值得养成习惯表名要有业务前缀方便在同一个库里区分业务模块每个表都尽量包含create_time、update_time、deleted、version这类公共字段后面配置自动填充、逻辑删除、乐观锁时一次搞定所有表都能受益字段注释必须写生成的Entity注释会直接来自数据库注释注释齐全的代码后续维护体验完全不一样。3. 生成器配置与代码实现3.1 新版FastAutoGenerator的完整主类MyBatis-Plus的生成器从3.5.3版本开始主推新版API类名叫FastAutoGenerator。相比旧版需要一堆new AutoGenerator()然后各种set的写法新版的链式配置更清晰扫码、全局配置、包配置、策略配置都在一个链式调用里完成。下面是我用过一段时间后一直在用的模板做了适量精简但保留最常用的配置项public class CodeGenerator { public static void main(String[] args) { FastAutoGenerator.create( jdbc:mysql://localhost:3306/demo?useUnicodetruecharacterEncodingUTF-8serverTimezoneAsia/ShanghaiuseSSLfalse, root, 123456 ) .globalConfig(builder - { builder.author(zhangsan) // 作者名注释里会带上 .enableSwagger() // 开启swagger注解配合knife4j/springdoc使用 .dateType(DateType.TIME_PACK) // 时间策略使用java.time包 .outputDir(System.getProperty(user.dir) /src/main/java); // 输出路径 }) .packageConfig(builder - { builder.parent(com.example.demo) // 父包名 .moduleName(system) // 模块名可选 .entity(entity) .service(service) .serviceImpl(service.impl) .mapper(mapper) .controller(controller); }) .strategyConfig(builder - { builder.addInclude(tb_user) // 要生成的表多张表用逗号隔开 .addTablePrefix(tb_) // 表前缀去掉后成为类名 .entityBuilder() .enableLombok() .enableTableFieldAnnotation() .logicDeleteColumnName(deleted) .versionColumnName(version) .controllerBuilder() .enableRestStyle() .serviceBuilder() .formatServiceFileName(%sService) .formatServiceImplFileName(%sServiceImpl) .mapperBuilder() .enableMapperAnnotation(); }) .templateEngine(new FreemarkerTemplateEngine()) .execute(); } }一个很多人刚开始不习惯的点是entityBuilder、controllerBuilder、serviceBuilder、mapperBuilder这些方法是嵌套在strategyConfig内部的。建议先记住一个大的结构strategyConfig里面通过不同子builder分别配置不同层级的策略写起来时不会把enableLombok和enableRestStyle写错了层级。3.2 全局配置输出目录、作者、时间类型globalConfig里面有几个容易踩坑的地方。outputDir控制的是最终代码输出到哪个目录常见的项目结构里代码要输出到src/main/java底下。这里我使用的是System.getProperty(user.dir)获取当前工程根目录然后拼接/src/main/java。如果你的项目是多模块Maven工程user.dir可能指向的是父工程目录输出位置会不对这时候建议直接用绝对路径或者在启动参数里指定项目模块路径。dateType字段值得多说两句。它控制的是时间字段生成的Java类型DateType.TIME_PACK会生成LocalDateTime、LocalDate这些Java 8时间类型DateType.ONLY_DATE会生成java.util.DateDateType.SQL_PACK则映射到java.sql.Date。现在的项目基本都用Java 8以上强烈建议选TIME_PACK。逻辑上系统时间字段用LocalDateTime处理日期型字段用LocalDate比老的Date类更清晰。enableSwagger这个配置需要特别提醒它会在生成的Entity和Controller上添加Swagger的注解比如Entity里生成ApiModelPropertyController里生成Api、ApiOperation。问题是如果你的项目里没有引入springdoc或knife4j这类Swagger依赖生成的代码会直接编译不通过。所以这个开关要么配合项目已有的Swagger依赖一起用要么干脆不开启你自己在模板里去控制。3.3 包配置包名的层次和位置packageConfig控制的是生成包名的根路径和子包结构。parent是根包名比如com.example.demo然后每层代码放在不同的子包下。moduleName是一个可选的中间模块名比如填了system最终生成的Entity全限定名就是com.example.demo.system.entity.TbUser。这个配置非常影响代码的组织方式。如果你的项目是多模块业务比如有system模块、order模块那么生成代码时可以通过修改moduleName来生成到不同模块路径下。如果你的项目是单模块我更建议不填moduleName让代码直接落在com.example.demo.entity这类清晰的路径下避免不必要的目录层级。子包名同样可以自定义。serviceImpl(service.impl)这里的含义是ServiceImpl放在service包下的impl子包里对应主流的实现类放子包规范。entity(entity)、mapper(mapper)这些也按个人习惯调整没有强制要求。只要保证生成后的代码可以被项目的包扫描覆盖到就行。3.4 策略配置真正需要花心思的地方策略配置是整个生成器的灵魂也是很多人配置得最混乱的地方。我在日常项目中固定使用这几组策略addInclude指定你要生成哪些表如果有多个表用tb_user, tb_role这种逗号分隔方式。注意如果没有写addInclude生成器默认不会扫描所有表而是要求你明确指定这是一个容易让人疑惑的地方。addTablePrefix表示生成类名时去掉的前缀。表名tb_user去掉tb_后再以下划线转驼峰规则变成User。如果你不想在类名里总带着前缀名这一步一定不能漏。entityBuilder里的enableLombok开启后Entity会生成Data注解而不是一堆getter/setter生成代码更简洁。enableTableFieldAnnotation会在每个字段上生成TableField注解虽然MyBatis-Plus默认开启驼峰映射后能自动关联但显式加上注解对后期维护和查看字段对应关系非常有帮助。逻辑删除和乐观锁的配置在Entity生成里是最实用的。logicDeleteColumnName(deleted)会把deleted字段自动标上TableLogic注解从此执行删除操作时自动变成UPDATE语句。versionColumnName(version)会在version字段上生成Version注解配合乐观锁拦截器实现并发控制。这两个字段只要在数据库表里存在配置好之后生成的代码直接就能用不需要再手动改。controllerBuilder里面enableRestStyle是生成RestController和基于RequestMapping的RESTful接口风格如果不开生成的是Controller配合方法的ResponseBody。现在的项目基本都用前后端分离建议保持打开。mapperBuilder里enableMapperAnnotation()控制是否在Mapper接口上生成Mapper注解。如果你的项目在启动类上已经用了MapperScan这个可以不开避免重复。3.5 模板引擎选哪个MyBatis-Plus生成器底层依赖模板引擎来渲染代码。官方默认内置的是Velocity如果你不配置任何模板引擎它会用Velocity渲染。如果你和我一样在pom里引入了Freemarker那么需要像第3.1节那样显式指定new FreemarkerTemplateEngine()。那选哪个好我个人更推荐Freemarker。主要原因不是功能差别而是Freemarker的模板语法在国内资料更多遇到需要自定义模板时查起来方便。模板引擎本身对生成结果没有太大影响只要配置正确生成出来的代码是完全一致的。如果你需要深度定制生成结果比如在Controller里改用构造器注入而不是Autowired或者给Service方法自动加上统一返回格式那就需要去改MyBatis-Plus生成的模板文件。模板在generator依赖的jar包里路径大致是templates/entity.java.ftl、templates/controller.java.ftl这样的命名。你可以把这些模板拷贝出来改成自己的版本再通过templateEngine指定自定义模板路径。这个操作我在第5.5节会再展开说日常使用可以先不改。4. 运行生成与产物解读4.1 执行main方法看输出日志配置写好之后直接右键运行CodeGenerator的main方法。控制台会出现类似下面的日志Connecting to the database... Loading table list... Loaded 1 tables. Generating entity file ... Generating mapper file ... Generating service file ... Generating serviceImpl file ... Generating controller file ... Successfully generated 5 files.日志信息比较简略但它背后干的活可不少先读取表结构元数据然后把每张表的字段、注释、主键、索引信息加载出来根据你的策略配置逐层渲染最后把文件写到指定目录。我运行完以后会习惯性地去outputDir目录核对一下文件数量确认Entity、Mapper、Service、ServiceImpl、Controller这五个文件都生成了。如果你的表非常多运行过程会稍长一些但一般表量在几十张以内都是秒级完成。建议一次生成一张或一批业务相关的表观察日志确认无误后再批量操作避免生成了一堆不需要的文件还要自己清理。4.2 生成的五件套长什么样生成完以后我们到com.example.demo.system.entity目录下看Entity内容大致如下package com.example.demo.system.entity; import com.baomidou.mybatisplus.annotation.*; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.time.LocalDateTime; Data TableName(tb_user) ApiModel(value TbUser对象, description 用户表) public class TbUser { TableId(value id, type IdType.AUTO) private Long id; TableField(username) private String username; TableField(password) private String password; TableField(age) private Integer age; TableField(email) private String email; TableField(status) private Boolean status; ApiModelProperty(创建时间) TableField(value create_time, fill FieldFill.INSERT) private LocalDateTime createTime; ApiModelProperty(更新时间) TableField(value update_time, fill FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; ApiModelProperty(逻辑删除0-未删除1-已删除) TableLogic private Integer deleted; ApiModelProperty(乐观锁版本号) Version private Integer version; }这里有几个细节可以重点观察。TableName(tb_user)是自动生成的说明列名到表名的映射已经处理好了。TableLogic和Version两个注解是策略配置里logicDeleteColumnName和versionColumnName的功劳没配置的话这里就是普通字段。createTime和updateTime上的fill FieldFill.INSERT、FieldFill.INSERT_UPDATE也来自生成器的内置处理这个要与代码里自定义的MetaObjectHandler配合后面说。Mapper接口也很干净package com.example.demo.system.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.example.demo.system.entity.TbUser; import org.apache.ibatis.annotations.Mapper; Mapper public interface TbUserMapper extends BaseMapperTbUser { }Service接口和ServiceImpl如下public interface TbUserService extends IServiceTbUser { }Service public class TbUserServiceImpl extends ServiceImplTbUserMapper, TbUser implements TbUserService { }Controller如下RestController RequestMapping(/system/tbUser) Api(tags 用户表) public class TbUserController { Autowired private TbUserService tbUserService; GetMapping(/list) public ListTbUser list() { return tbUserService.list(); } GetMapping(/{id}) public TbUser get(PathVariable Long id) { return tbUserService.getById(id); } PostMapping public boolean save(RequestBody TbUser tbUser) { return tbUserService.save(tbUser); } PutMapping public boolean update(RequestBody TbUser tbUser) { return tbUserService.updateById(tbUser); } DeleteMapping(/{id}) public boolean delete(PathVariable Long id) { return tbUserService.removeById(id); } }注意Controller的路径是/system/tbUser这个路径是根据包名moduleName和表名驼峰化生成的。如果你不喜欢这个规则可以在controllerBuilder里配置formatFileName或者在自定义模板中修改RequestMapping的值。生成的Controller只是为了快速提供最基础的CRUD能力真正复杂的业务接口还是要基于Service去扩展。4.3 生成完不是终点接入项目还需要这几步文件生成之后不是启动项目就能直接用的。你需要确认三类东西已经配好第一类是MyBatis-Plus的分页插件和逻辑删除插件。逻辑删除用到了TableLogic乐观锁用到了Version这些只加注解还不够需要在配置类里注入对应拦截器Configuration public class MybatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; } }第二类是自动填充处理器。Entity上的fill FieldFill.INSERT和fill FieldFill.INSERT_UPDATE只是声明了哪些字段需要自动填充真正执行填充逻辑的是MetaObjectHandler的实现类比如Component public class MyMetaObjectHandler implements MetaObjectHandler { Override public void insertFill(MetaObject metaObject) { this.strictInsertFill(metaObject, createTime, LocalDateTime.class, LocalDateTime.now()); this.strictInsertFill(metaObject, updateTime, LocalDateTime.class, LocalDateTime.now()); } Override public void updateFill(MetaObject metaObject) { this.strictUpdateFill(metaObject, updateTime, LocalDateTime.class, LocalDateTime.now()); } }第三类是包扫描。虽然Mapper接口上你配置了Mapper但如果你的项目统一用MapperScan来扫包就需要把com.example.demo.system.mapper这个包路径加上。上面几项配完启动项目后生成的CRUD接口就可以直接通过HTTP调用了。5. 常见报错与经验汇总5.1 版本兼容性问题跑不起来先查版本生成器相关的报错十次有八次是版本问题。我把常见的版本坑列一下供你对照自查。如果你的项目是SpringBoot 3.x还在用mybatis-plus-boot-starter启动时大概率会报找不到org.apache.ibatis.session.Configuration相关的类或者MyBatis-Plus自动装配失败。解决办法就是把starter换成mybatis-plus-spring-boot3-starter。mybatis-plus-generator的版本也容易踩坑。3.5.3版本之前和之后的API差异很大网上搜到的教程很多是旧版写法类名还是AutoGenerator。我建议直接使用3.5.7及以上版本并严格跟随新版FastAutoGenerator的API来写。还有JDK版本的匹配问题。SpringBoot 3.x要求JDK 17及以上如果你本机同时装了多个JDK版本运行生成器时IDE可能会选中旧版本导致启动就报不支持class文件版本错误。建议在IDE里把项目的Language level和SDK统一调整为17或更高。5.2 表名识别不到或生成的类名不符合预期有同学反馈addInclude(tb_user)配置了运行却提示找不到表。这个问题在Windows本地上尤其常见原因大多是MySQL的lower_case_table_names参数不一致。如果你的表名在库里的实际值是TB_USER而配置里写的是tb_user在部分Linux环境或大小写敏感配置下就会匹配不上。排查方式很简单在数据库客户端里执行show tables;确认实际表名再原样填写。如果生成出来的类名多了一段前缀比如TbUser变成了TbTbUser那就是addTablePrefix(tb_)没有生效。看看是不是把配置写在了globalConfig里而不是strategyConfig的entityBuilder链路上。表前缀处理是策略配置的一部分写错层级会导致生成器完全忽略。还有一种情况是配置里同时写了addTablePrefix(tb_)和addTableSuffix如果你本来就没想清楚要不要后缀建议先统一不加后缀生成后再review代码保持类名整洁。5.3 字段类型映射不符合预期生成器对字段类型的映射规则是内置了一套的绝大多数情况够用但还是有一些特殊场景会触发困惑。最典型的就是tinyint(1)字段。在MySQL里tinyint(1)经常被用来表示布尔值生成器默认也会把它映射为Boolean。但有时候你的tinyint(1)其实是一个状态值比如状态字段只存0和1你希望它映射为Integer而不是Boolean。解决方式是自定义typeConvertHandler示例如下.typeConvertHandler((globalConfig, typeRegistry, metaInfo) - { if (metaInfo.getJdbcType() JdbcType.TINYINT) { return Integer.class; } return typeRegistry.getColumnType(metaInfo); })另一个常见问题是datetime映射成LocalDateTime后前端传参格式不对导致接口报错。这个不属于生成器的问题而是序列化配置问题但很容易被人误认为是生成代码的Bug。5.4 重新生成时文件被覆盖或每次生成都要手动清目录这个坑我踩过不止一次。生成器默认情况下如果目标文件已经存在是不会覆盖的。这本来是为了保护你手写的代码但也带来一个麻烦你修改了表结构重新运行生成器发现代码还停留在旧状态。排查方法也很简单看strategyConfig里有没有启用FileOverride。没有的话想强制覆盖就在对应的Entity或Mapper策略里加上enableFileOverride()。这里必须提醒一句FileOverride是双刃剑。如果你在生成的类上手动改过代码比如ServiceImpl里写了额外的业务方法强制覆盖会把这些代码全部冲掉。我见过有同事因为没注意覆盖策略整个Service层的自定义逻辑全部丢失。稳妥做法是启用覆盖前先把整个生成目录提交一次Git生成完可以随时diff出改动。5.5 生成器代码不放业务工程里维护起来更轻松最后一个建议也是长期项目里很重要的一点把生成器代码本身独立出来。不要像我最早一样把CodeGenerator.java放在业务工程的src/main/java目录下。这样会导致业务工程多出mybatis-plus-generator和模板引擎等一堆编译期依赖还会被部分公司的基础设施扫描到提前引入不必要的安全审计问题。我现在的做法是在项目根目录下建一个单独的codegenMaven模块专门放生成器的配置和自定义模板它只依赖数据库驱动、generator和模板引擎不依赖任何业务代码。每次需要生成代码时单独运行这个模块的main方法即可。这样业务工程的依赖干净生成器代码升级或替换也不会影响到线上编译。如果你暂时不想拆模块也可以把生成器代码放进业务工程的src/test/java目录下让它只存在于测试源码集中同样不会污染主构建链。另外如果希望生成出来的代码更贴合自己团队的习惯比如用RequiredArgsConstructor构造器注入替代Autowired把Controller返回结果统一包一层ResultT那就不要只在代码里改建议直接修改模板文件。我的做法是先把generator jar包里对应的ftl模板拷出来放到codegen模块的resources/templates目录下修改后通过templateEngine.builder()...build()指定模板路径。这样以后不管生成多少张表代码风格都一致新人接手也不会跑来问“为什么这个项目的Controller写法和模板不一样”。最后分享一个我养成的小习惯项目里所有表都统一带id、create_time、update_time、deleted、version这五个公共字段生成器配置里固定打开逻辑删除、乐观锁和自动填充。这套组合我用了将近两年几乎没有因为并发更新、数据误删或者时间字段漏填出过线上问题。生成器能自动完成的事千万别靠人肉记忆去保证每次一致。后来我把这段生成器配置沉淀成了团队内部的初始化模板新成员拉下来改一下数据库地址就能跑几天之内就能把一堆旧手写代码全部批量换成统一风格的生成代码。与其重复造轮子不如把造轮子的过程交给工具这也是我建议你尽快上手MyBatis-Plus自动代码生成器的最直接理由。
返回列表