一、工具背景MBG 只能生成 model、mapper。我们封装通用父接口BaseDao、BaseService每新增一张数据表仍然需要手写 4 类文件Query 查询对象带 pageNo、startNum 分页字段Mapper Dao 接口Service 业务接口ServiceImpl 实现类复制粘贴模板代码很容易写错包名、类名。自定义代码生成器原理准备 tpl 模板文件IO 读取模板 字符串替换类名一键生成 4 份 Java 模板代码。注意只生成 Java 模板Mapper.xml 中的动态分页、条件 SQL 依旧需要自己手写。二、通用父接口模板依赖BaseDao.javapackage cn.tx.dao; import cn.tx.util.Page; import java.util.List; public interface BaseDaoQ, T { void insert(T t); T selectByPrimaryKey(Integer id); int deleteByPrimaryKey(Integer id); void updateByPrimaryKeySelective(T t); ListT selectObjectByCondition(Q q); int selectObjectByConditionCount(Q q); }BaseService.javapackage cn.tx.service; import cn.tx.util.Page; public interface BaseServiceQ, T { int insert(T t); T selectByPrimaryKey(Integer id); int deleteByPrimaryKey(Integer id); void updateByPrimaryKeySelective(T t); PageT selectObjectByCondition(Q q); }BaseServiceImpl.javapackage cn.tx.service.impl; import cn.tx.dao.BaseDao; import cn.tx.service.BaseService; import cn.tx.util.Page; import java.lang.reflect.Method; public class BaseServiceImplQ,T implements BaseServiceQ,T { protected BaseDaoQ, T baseDao; Override public int insert(T t) { return baseDao.insert(t); } Override public T selectByPrimaryKey(Integer id) { return baseDao.selectByPrimaryKey(id); } Override public int deleteByPrimaryKey(Integer id) { return baseDao.deleteByPrimaryKey(id); } Override public void updateByPrimaryKeySelective(T t) { baseDao.updateByPrimaryKeySelective(t); } Override public PageT selectObjectByCondition(Q q) { Class? qclass q.getClass(); PageT page new Page(); try { Method getPageNo qclass.getMethod(getPageNo); Integer pageNo (Integer) getPageNo.invoke(q); page.setPageNo(pageNo); Method setStartNum qclass.getMethod(setStartNum,int.class); int startNum page.getStartNum(); setStartNum.invoke(q,startNum); }catch (Exception e){ e.printStackTrace(); } ListT list baseDao.selectObjectByCondition(q); int total baseDao.selectObjectByConditionCount(q); page.setTotalCount(total); page.setList(list); return page; } }三、tpl 模板文件路径core/src/test/resources/tpl一共 4 个模板文件。DemoQuery.tplpackage cn.tx.query; import cn.tx.model.Demo; public class DemoQuery extends Demo { private Integer pageNo; private Integer startNum; public Integer getPageNo() { return pageNo; } public void setPageNo(Integer pageNo) { this.pageNo pageNo; } public Integer getStartNum() { return startNum; } public void setStartNum(Integer startNum) { this.startNum startNum; } }DemoMapper.tpl package cn.tx.dao; import cn.tx.model.Demo; import cn.tx.query.DemoQuery; public interface DemoMapper extends BaseDaoDemoQuery, Demo{ }DemoService.tplpackage cn.tx.service; import cn.tx.model.Demo; import cn.tx.query.DemoQuery; public interface DemoService extends BaseServiceDemoQuery, Demo{ }DemoServiceImpl.tplpackage cn.tx.service.impl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import cn.tx.dao.DemoMapper; import cn.tx.model.Demo; import cn.tx.query.DemoQuery; import cn.tx.service.DemoService; Service public class DemoServiceImpl extends BaseServiceImplDemoQuery, Demo implements DemoService { private DemoMapper demoDao; Autowired public void setDemoDao(DemoMapper demoDao) { this.demoDao demoDao; this.baseDao demoDao; } }四、代码生成器执行类 SourceGenerator.javapackage cn.tx.util; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter; public class SourceGenerator { public static void main(String[] args) throws Exception { //传入实体类名首字母大写如Mtype、Album、Songer generatorSource(Mtype); } public static void generatorSource(String objName) throws Exception{ generateQuery(objName); generateDao(objName); generateService(objName); generateServiceImpl(objName); } //生成Query查询对象 public static void generateQuery(String objName) throws Exception{ BufferedReader br new BufferedReader(new FileReader(core/src/test/resources/tpl/DemoQuery.tpl)); BufferedWriter bw new BufferedWriter(new FileWriter(core/src/main/java/cn/tx/query/objNameQuery.java)); String line; while((line br.readLine()) ! null){ line line.replace(Demo, objName); bw.write(line); bw.newLine(); } bw.close(); br.close(); } //生成Mapper Dao接口 public static void generateDao(String objName) throws Exception{ BufferedReader br new BufferedReader(new FileReader(core/src/test/resources/tpl/DemoMapper.tpl)); BufferedWriter bw new BufferedWriter(new FileWriter(core/src/main/java/cn/tx/dao/objNameMapper.java)); String line; while((line br.readLine()) ! null){ line line.replace(Demo, objName); bw.write(line); bw.newLine(); } bw.close(); br.close(); } //生成Service接口 public static void generateService(String objName) throws Exception{ BufferedReader br new BufferedReader(new FileReader(core/src/test/resources/tpl/DemoService.tpl)); BufferedWriter bw new BufferedWriter(new FileWriter(core/src/main/java/cn/tx/service/objNameService.java)); String line; while((line br.readLine()) ! null){ line line.replace(Demo, objName); bw.write(line); bw.newLine(); } bw.close(); br.close(); } //生成ServiceImpl实现类 public static void generateServiceImpl(String objName) throws Exception{ String lowerObjName objName.substring(0,1).toLowerCase()objName.substring(1); BufferedReader br new BufferedReader(new FileReader(core/src/test/resources/tpl/DemoServiceImpl.tpl)); BufferedWriter bw new BufferedWriter(new FileWriter(core/src/main/java/cn/tx/service/impl/objNameServiceImpl.java)); String line; while((line br.readLine()) ! null){ line line.replace(Demo, objName); line line.replace(demo, lowerObjName); bw.write(line); bw.newLine(); } bw.close(); br.close(); } }五、使用方法修改 main 方法参数传入首字母大写实体类名运行 main 方法自动生成 Query、Mapper、Service、ServiceImpl。踩坑清单tpl 模板路径以父工程为根目录否则报FileNotFoundException。模板内package包名必须和项目实际包名完全一致。传入类名首字母大写代码内部自动转小写作为变量。不要删除DemoServiceImpl.tpl中的Service注解否则 Spring 无法注入 Bean。六、两套生成器对比工具来源输出文件能力限制MyBatis‑Generator(MBG)MyBatis 官方model、Mapper 接口、Mapper.xml仅持久层不生成 Service 与业务 SQL自定义代码生成器手写 IO 字符串替换Query、Mapper、Service、ServiceImpl只生成 Java 模板SQL 需要手动写依赖 tpl 模板七、一张数据表完整开发流程MySQL 执行建表 SQL创建数据表运行 MBG 逆向工程生成 model、mapper 基础文件运行自定义代码生成器生成业务层全套模板Mapper.xml 手写动态条件、分页 SQL编写 Controller调用 Service 完成业务重点生成器只是减少复制粘贴不能替代业务开发复杂逻辑、SQL 必须手写。八、常见异常FileNotFoundException检查运行工作目录、模板文件路径ClassNotFoundException执行mvn clean compile编译NoSuchMethodException getPageNoQuery 缺少分页 get/set重新运行生成器Bean 为 nullServiceImpl 缺少Service注解SQL 列找不到mapper.xml 数据库字段名书写错误。九、总结MBG 负责数据库表转持久层代码自定义生成器解决业务层模板重复代码。适合封装通用BaseDao/BaseService的 SSM 项目课程作业、练手项目效率提升明显。Maven 聚合项目优先排查相对路径、Maven 编译缓存。工具只是辅助业务 SQL、业务逻辑仍然由开发人员编码。