代码生成插件EasyCode实战:配置、模板与踩坑指南
1. 为什么我会折腾代码生成工具干后端开发的谁没被CRUD折磨过。业务接口、DAO层、Mapper文件、Service实现写来写去就那么几套固定的套路查列表、查单条、插入、更新、删除。每个表都得来一遍新表多了以后一上午时间基本就耗在这上面了。我最早是手动复制模板再改表名后来也试过自己写freemarker脚本生成但维护脚本本身也是成本。直到有个同事给我推荐了EasyCode这个IDEA插件我才真正觉得这问题算是彻底解决了。EasyCode是一个基于IntelliJ IDEA的代码生成插件核心思路很直接你连上数据库选中一张表它就能按照你预设的模板批量生成对应的实体类、Mapper接口、XML映射文件、Service、ServiceImpl和Controller。它本身不绑定任何框架Spring Boot配MyBatis、MyBatis Plus、JPA都能用关键在于模板完全可定制用的是Velocity模板引擎。这个工具适合谁如果你是每天要处理大量数据表的业务开发或者团队刚立项想统一代码规范又或者你只是不想一遍遍敲那些重复的getter和setterEasyCode都值得花半小时研究一下。它不挑项目规模一个小接口也能用一套微服务照样能跑。这篇文章我按自己的实操路线把从安装、配置、生成到自定义模板的完整流程写一遍顺便把我踩过的坑都列出来照着做基本能少走一半弯路。2. 安装配置与前置准备2.1 插件安装两个路径随便选EasyCode的安装没什么特殊门槛。打开IDEA进入File - Settings - Plugins在Marketplace搜索框里输入EasyCode找到那个图标是绿色闪电的工具点击Install然后重启IDE就行。如果你的网络环境访问插件市场不太稳定也可以去JetBrains插件仓库直接下载zip包然后通过Install Plugin from Disk安装注意选压缩包而不是解压后的文件夹。有一点要留个心眼EasyCode的版本和你的IDEA版本有兼容性要求。旧版IDEA2020之前装新版插件很可能直接提示插件版本不兼容导致无法启用。我见过有人卡在这里怎么装都装不上最后发现就是IDE版本太老。装机前先确认一下自己IDEA的版本号能省不少事。安装完成之后IDEA右侧工具栏会出现一个EasyCode的侧边栏面板里面能看到数据库连接信息、模板列表和生成记录。如果你打开后是空的别急那是还没配置数据源。2.2 数据库连接生成代码的前提EasyCode本身不带数据库连接功能它依赖IDEA内置的Database面板。也就是说你先得让IDEA能连上你的库EasyCode才能读表结构来生成代码。这个先后顺序很多人弄反了一直在EasyCode面板里找连接入口自然找不到。操作路径是IDEA右侧Database面板 - 左上角加号 - Data Source - 选择你的数据库类型MySQL、PostgreSQL、Oracle、SQL Server都支持。以最常见的MySQL为例填Host、Port、User、Password、Database名称。填完先点Test Connection测试连通性显示Succeeded之后再点OK保存。这里有个常见坑测试连接报Server returns invalid timezone。这是MySQL驱动8.x版本对时区敏感导致的。解决办法是在Connection URL末尾加上参数比如jdbc:mysql://localhost:3306/demo_db?serverTimezoneAsia/ShanghaiuseSSLfalseallowPublicKeyRetrievaltrue。这三个参数我建议都写上serverTimezone解决时区报错useSSLfalse避免SSL握手告警allowPublicKeyRetrievaltrue解决某些MySQL版本需要获取公钥的问题。2.3 连接配置里的细节参数如果你用的是公司内网数据库可能还要涉及SSH隧道或者只读账号这些在Database面板的Advanced/SSH标签页里都有对应配置项按公司提供的参数填即可。我个人建议连库用一个有SELECT权限的账号就够了EasyCode只需要读取表结构和字段元数据不需要写权限用最小权限原则能避免误操作。另外有个小细节连上数据库之后记得在Database面板里展开表列表右键选择要生成的表会看到EasyCode的入口菜单。如果你的表特别多比如几百张可以配合IDEA的搜索过滤功能先筛选不然下拉列表看着也累。3. 模板体系EasyCode的心脏3.1 内置模板到底帮我们生成了什么EasyCode的魅力不在生成按钮而在那套模板体系。它默认带了一套基于Spring Boot MyBatis风格的模板包括entity.java、dao.java、service.java、serviceImpl.java、controller.java和mapper.xml这六个文件。你选中一张表执行生成它会在指定包路径下把这六个文件全部创建出来对应关系大致是这样的模板文件生成的类主要职责entity.java实体类对应表字段含Getter/Setterdao.javaDAO接口定义数据访问方法mapper.xmlMyBatis映射文件SQL语句与结果映射service.javaService接口业务逻辑接口定义serviceImpl.javaService实现业务逻辑实现controller.java控制器REST接口入口理解这个结构之后你就会明白为什么说EasyCode是模板驱动的生成工具它生成的代码长什么样完全由模板决定而不是插件写死的。默认模板生成的是经典MyBatis风格的代码如果你的项目用的是MyBatis Plus默认模板生成的DAO接口其实不太合适需要自己调整模板让DAO继承BaseMapperT。这个我们在后面自定义模板的部分细说。3.2 Velocity模板语法速通EasyCode的模板基于Apache Velocity引擎写起来比Freemarker还要简洁。核心语法就三个记熟了基本就能改模板变量渲染用$符号开头比如$!tableInfo.name表示当前表的表名加!的意思是如果变量为空就输出空字符串而不是null。整表遍历用#foreach($column in $tableInfo.fullColumn)循环体里面$column.name是字段名、$column.comment是注释、$column.obj是对应Java类型信息。条件判断用#if($column.type.equals(String))这种形式配合#end结束。模板里的换行和缩进会直接带进生成结果。这个细节很关键我就因为模板里多了一个多余的空行生成的实体类里每两个字段之间都有一个空行代码风格检查直接报错。所以改模板时宁可紧凑一点也别留游离的空行调一次Scalar格式成本很高。3.3 类型映射数据库字段到Java类型的桥梁数据库里的一张表在模板里通过$tableInfo这个对象访问字段列表通过$tableInfo.fullColumn拿到。每个字段对象$column身上带着数据库类型、Java类型、注释、字段名等属性。其中类型映射的逻辑是EasyCode会读数据库字段类型然后映射到对应的Java类型比如数据库的varchar映射为Stringbigint映射为Longdatetime映射为Date。这个映射关系是可配置的。在EasyCode面板里有个Type Mapper的Tab页列出了各种数据库类型到Java类型的对应表。如果你的项目里时间字段用的是LocalDateTime而不是java.util.Date直接在这个映射表里改即可。改完之后所有模板里的$column.obj.type都会跟着变比到每个模板里逐个改要高效得多。4. 一键生成代码的完整实操4.1 生成前的工程准备到了实操环节我建议你先花两分钟把包路径想清楚。EasyCode生成代码时要求你指定一个根包路径packageName它会在这个包下面按controller、service、dao、entity、mapper这样的子包结构自动建目录并放文件。比如你的项目groupId是com.example.demo通常填com.example.demo作为rootPackage生成时自然会创建出com.example.demo.controller这样的包。如果你的项目是多模块工程每个子模块有自己的根路径那就分别对每个模块执行生成选对应的路径。另外确认一下项目里是否已经存在同名的文件EasyCode默认会跳过已存在的文件不会覆盖除非你在生成对话框勾选了覆盖选项。第一次用的人容易困惑怎么没生成其实大部分情况就是文件已存在被跳过了。4.2 选中表和生成参数在Database面板里右键点击目标表可以多选选择EasyCode - Generate Code。此时会弹出生成对话框左侧是模板分组列表右侧是根包路径、实体类名、是否需要Lombok等选项。我的习惯是这样的单表操作直接右键生成多张表一起生成时先按业务模块筛选好表再一起选这样生成的包结构整齐。对话框里的模板分组如果之前没自定义过就选默认Default分组。实体类名默认是表名去掉下划线转驼峰比如user_info变成UserInfo这个规则一般不用动。有一个值得注意的参数是实体类名后缀很多项目习惯在实体类后面加Entity后缀比如UserEntity。模板里默认没有这个后缀你可以在生成对话框里直接改或者去模板配置里加全局变量统一控制。我更推荐改模板因为对话框里每次都要手动填容易漏。4.3 生成结果验收我的检查清单代码生成不是点完按钮就完事了我每次都会按下面这个清单过一遍第一检查实体类字段类型。特别是那些数据库里定义得很随意的小数字段比如tinyint默认映射成了Byte但业务上这个字段可能是个状态码用Integer更合适。这个在Type Mapper里可以全局改但更稳妥的做法是生成完肉眼扫一遍。第二检查Mapper XML里的SQL语法。EasyCode生成的SQL基础语句基本可靠但遇到多表关联、复杂where条件还是得自己补。生成结果只能算脚手架别指望它完成全部业务逻辑。第三编译测试。生成完先跑一下mvn compile确认没有任何引用错误再继续往下写代码。引入EasyCode之后我养成的习惯是生成完第一时间编译有问题当场处理不要堆到后面。5. 自定义模板实战把团队规范固化到模板里5.1 为什么不满足于默认模板默认模板生成的代码能跑但真的只停留在能用的水平。比如默认模板生成的Controller里没有统一返回格式没有全局异常处理注解实体类上也没有TableName这种MyBatis Plus注解。说白了默认模板是给一个干净的新项目准备的如果你的项目有自己的一套代码规范比如所有Controller必须继承一个BaseController或者所有实体类必须实现序列化接口那默认模板生成的代码就得一个个手动改生成了等于没生成。所以我的建议是拿到插件先别急着用花半小时把模板改成符合自己团队规范的样子这是一次性投入长期受益的事情。代码质量的核心其实不是生成工具本身而是模板内容的约束能力。模板写好了每一个新表生成的代码都是齐整的代码review的压力会小很多。5.2 模板编辑器里怎么动手改EasyCode面板的第二个Tab就是Template模板列表双击某个模板可进入编辑界面。界面左边是模板代码右边是变量说明和语法提示改动保存后立即生效不需要重启IDEA。举个例子。默认的dao.java模板生成的是纯粹的接口方法定义。如果你的项目用MyBatis Plus想让生成的DAO接口继承BaseMapperUserInfo只需要在模板里把接口声明改成这样public interface $!{tableInfo.name}Dao extends BaseMapper$!{tableInfo.name} { }同时把Mapper XML里内置的那些基础SQL删掉因为MyBatis Plus内置了通用方法再生成一遍xml反而会有重复的select/insert语句。这个改动看着小但能让生成的代码一下子贴合MyBatis Plus的开发方式。再比如Controller模板我习惯让生成的类带上RestController和RequestMapping注解并且方法统一返回项目自定义的ResultT包装类。模板里直接写死返回类型生成出来每个Controller就都统一了。5.3 一套我常用的模板写法参考这里分享一个我改过的Service接口模板片段算是抛砖引玉package $!{package.Service}; import $!{package.Entity}.$!{tableInfo.name}; import com.baomidou.mybatisplus.extension.service.IService; /** * $!{tableInfo.name} 服务接口 */ public interface $!{tableInfo.name}Service extends IService$!{tableInfo.name} { /** * 分页查询 */ Page$!{tableInfo.name} queryPage($!{tableInfo.name} query, int pageNum, int pageSize); }注意模板里用到$!{package.Service}和$!{package.Entity}这两个变量它们是EasyCode根据根包路径自动计算出来的子包路径。模板写多了之后你会发现EasyCode提供了一套上下文变量包括当前表信息、包路径、作者、日期等在编辑界面右侧都能查到说明。改模板的核心原则就一条以你项目里手写最顺手的那个类为蓝本把它提炼成模板。不要把别处的规范硬塞进模板比如你们项目本身不用Lombok模板里就不该出现Data注解生成的代码要符合团队真实工作方式才算好模板。5.4 模板分组的妙用EasyCode支持配置多个模板分组Group每个分组里可以放完全不同的一套模板。这功能微服务场景下特别好用。比如你的基础服务用MyBatis Plus报表服务用原生MyBatis两个项目的代码风格不一样那就配两个分组生成时选对应的分组就行不用来回改模板。分组之间支持复制如果新的分组只是某些模板不一样可以先复制再增量修改效率高很多。6. 常见问题排查实录6.1 高频问题速查表我把这一年多用到EasyCode的典型问题整理了张表按出现频率排了个序现象原因解决办法测试连接失败报timezone错误MySQL驱动时区问题URL加serverTimezoneAsia/Shanghai右键表没有Generate Code选项未打开Database面板且选中表确认表是在Database面板里右键生成后文件没出现文件已存在被跳过勾选覆盖选项或先删旧文件生成的实体类字段是乱码数据库表注释/字段注释编码异常连接URL加characterEncodingutf-8生成代码报模板语法错Velocity模板里有未定义变量加!使变量为空时输出空串接口方法生成了但XML没有对应SQL模板组里没勾选mapper.xml进入模板分组把xml模板勾上bigint映射成了Long但我想用String类型映射默认规则在Type Mapper里修改对应映射6.2 三个典型案例的排查思路第一个案例是生成出来的Controller类名不对。我们有个表叫t_order_detail_infoEasyCode默认转驼峰生成TOrderDetailInfo但项目规范要求类名去掉前缀T_变成OrderDetailInfo。这个处理有两个思路一是改模板在类名取值时做字符串处理二是直接改表名如果表名前缀是历史遗留改表名就不现实。我用的方案是在模板里加一行velocity判断判断表名以t_开头则截取后续部分实现起来也很简单#set($className $!tableInfo.name.substring($!tableInfo.name.indexOf(_) 1))然后所有用到类名的地方都换成$className变量。第二个案例是生成的Mapper XML无法正常绑定。现象是运行时报Invalid bound statement (not found)。排查后发现原因是我生成的xml文件被放到了resources目录之外MyBatis扫描不到。解决方案是确保生成路径选的resources里对应的mapper目录而且mybatis配置里的mapper-locations要指向那个路径。这个和EasyCode本身无关但用生成工具的人十个有八个会遇到特此记录。第三个案例是数据库驱动缺失问题。IDEA的Database面板里如果没下载对应数据库的驱动连接就会报Cannot connect: Driver not found。处理办法是在数据源配置界面点Download Driver按钮让IDEA自动下载驱动。内网环境如果下载不了就手动把驱动的jar包加到IDEA的驱动库路径里。6.3 排查思路总结用EasyCode遇到问题我的排查顺序是先看数据库连接是否正常再看模板是否有语法问题最后再看生成路径是否正确。九成问题都出在这三个环节。与其每次排查一遍不如把这些检查项记下来形成一个自己的清单时间长了基本看一眼报错就能定位。7. 我踩过的坑和一些心得讲几个只有实际用才会发现的细节。第一关于覆盖策略。EasyCode默认不覆盖已有文件这个特性既是保护也是坑。有时候我改了模板重新生成同一批表本以为能覆盖更新结果发现文件压根没变。后来我养成一个习惯改完模板需要重新生成时先手动清理掉旧的生成文件再执行生成。虽然多一步操作但心里有底不会出现新旧代码混在一起的局面。第二关于Lombok的取舍。默认实体类模板生成的是一堆Getter/Setter方法代码量很大。如果你的项目引入了Lombok强烈建议把实体类模板改成只保留Data注解加字段定义。生成出来十几行的类看着神清气爽。但有一点要提醒Lombok编译期生效如果团队里有人不开Lombok插件或者用的IDE版本不兼容编不过这就不是生成工具能管的事了。第三关于生成代码的责任边界。EasyCode能帮你生成基础骨架但别把一次性代码生成工具当成代码维护工具。不要想着以后每次表结构变了都重新生成一次来覆盖代码那会把你在业务方法里写的逻辑全冲掉。正确姿势是表结构稳定的阶段用生成器建好骨架之后业务代码全部手写迭代。表结构变动时用数据库迁移工具去改表再手动同步修改相关代码。这样既享受了生成效率又不会让生成器成为代码的隐患。第四关于模板版权和团队沉淀。公司内部的代码模板其实是一笔隐形财富。我建议模板统一改好后导出成文件放到团队内部的代码仓库里新同事入职拉下来直接导入IDEA大家生成出来的代码风格天然一致。这种标准化带来的好处比想象中大得多。我自己用EasyCode一年多最深的感受是这类工具的上限不取决于插件本身而取决于你愿不愿意花时间去打磨模板。默认模板只解决了从零到一的问题自定义模板才真正解决了从一到统一规范的问题。花半小时把模板改成适合自己的样子后面每天都能省出至少一两个小时这笔账怎么算都划算。