AI 时代持久层开发的动态最优解:从 7:2:1 到 5:3:2,约束强度决定一切
AI 时代持久层开发的动态最优解:从 7:2:1 到 5:3:2,约束强度决定一切
为什么 SimpleDAO 能防止 AI 生成 MyBatis 屎山代码?
摘要
AI 能写代码,但写不出好架构。本文提出 AI 时代持久层开发的“动态比例模型”——AI 与代码生成器是互补关系,不是替代关系,更不是对立关系。
- 传统代码生成器:承担50%~80%的确定性工作(表 → 代码的精确映射)
- AI:承担15%~30%的不确定性辅助(设计建议、性能分析、Bug 定位)
- 人:聚焦5%~30%的核心决策(架构、业务规则、最终把关)
比例不是固定的。它随工程规范约束强度、场景复杂度、人的控制能力动态调整。
基于Spring JDBC Ultra(SimpleDAO)的 SQL-First 范式,我们证明:防止 AI 写出屎山代码的唯一方法,是在范式层面做减法——将 AI 的"创造性"约束在可控范围内,而不是在代码层面做事后审查。
AI 万能论是片面的,AI 的代价是高昂的。
一、AI 写代码的"三重幻觉"与三重真实成本
幻觉 1:AI 写得快 = 效率高
场景:从数据库表生成一套完整 CRUD(Entity + DAO + Service + Controller + 前端 + 测试) AI(GPT-4)路径: 写 Prompt(描述表结构 + 生成规则) 2 分钟 等待生成 15 秒 检查输出,发现字段映射错误 3 分钟 写修正 Prompt 1 分钟 再次生成 15 秒 发现 Swagger 注解遗漏 2 分钟 发现前端控件类型不匹配 2 分钟 第三轮交互... ... 总计:10-15 分钟,Token 消耗数千 传统生成器(SimpleDAO)路径: 配置数据源 30 秒 选择表 + 选择模板 10 秒 点击生成 < 1 秒 总计:< 1 分钟,0 Token 消耗AI 的单轮生成快,但"达到可用状态"的总时间更长、成本更高。
幻觉 2:AI 写得对 = 确定性高
| 维度 | 传统生成器 | AI |
|---|---|---|
| 相同输入,相同输出 | ✅ 100% 可重复 | ❌ 温度参数导致变异 |
| 字段名拼写一致性 | ✅ 模板保证 | ❌ 可能驼峰/下划线混用 |
| 注解完整性 | ✅ 规则驱动 | ❌ 可能遗漏 @Schema |
| 前端控件类型匹配 | ✅ 类型映射表 | ❌ 可能把 Integer 映射成 Text |
| 代码风格一致性 | ✅ 模板统一 | ❌ 受 Prompt 描述影响 |
AI 的"创造性"在工程化场景中是负债,不是资产。
幻觉 3:AI 能替代传统代码生成器
这是最大的幻觉。AI 和生成器不是替代关系,是互补关系。它们解决的是完全不同的问题:
AI 的舒适区:不确定性 · "帮我设计一个支持分库分表的订单系统" · "这个慢查询怎么优化?" · "这段代码有什么并发问题?" 生成器的舒适区:确定性 · "表结构已定,生成全套 CRUD" · "字段类型已定,生成前端表单" · "API 路径已定,生成 Swagger 文档"AI 的三重真实成本
| 成本类型 | 说明 | 量化 |
|---|---|---|
| 训练成本 | AI 需要理解框架的私有语法(XML、OGNL、Criteria API) | 每个框架需数千 Token 上下文 |
| 生成成本 | 每次推理消耗 Token,复杂场景需多轮交互 | 单次 500-5000 Token |
| 持续交互成本 | 发现错误 → 修正 Prompt → 重新生成 → 再检查 | 时间成本 5-10 倍于生成器 |
SimpleDAO 的 SQL-First 范式将三重成本压缩到常数级:
- 训练成本 ≈ 0(SQL 是 AI 原生语言,无需学习私有语法)
- 生成成本 ≈ 0(生成器本地执行,零 Token)
- 持续交互成本 ≈ 0(输出即最终代码,无需修正)
AI 万能论的支持者只看到了 AI 的"生成速度",忽略了 AI 的"三座成本大山"。
二、动态比例模型:约束强度决定一切
2.1 核心公式
比例不是固定的,是约束强度的函数: ┌─────────────────────────────────────────┐ │ 约束强度维度 │ │ · 工程规范文档的完备度 │ │ · 代码审查流程的严格度 │ │ · 测试覆盖率要求 │ │ · 审计合规要求 │ │ · 团队技术成熟度 │ │ · 场景复杂度(单表 CRUD → 13 表联查) │ │ · 人的控制能力(架构经验、业务理解) │ ├─────────────────────────────────────────┤ │ 动态比例公式 │ │ │ │ 生成器% = 80 - 约束强度系数 × 30 │ │ AI% = 15 + 约束强度系数 × 10 │ │ 人% = 5 + 约束强度系数 × 20 │ │ │ │ 约束强度系数:0(极松)~ 1(极严) │ └─────────────────────────────────────────┘2.2 典型场景对照
| 团队类型 | 约束强度 | 比例(生成器:AI:人) | 原因 |
|---|---|---|---|
| 个人开发者/原型项目 | 0.1 | 77:16:7 | 几乎无规范,生成器大包大揽 |
| 创业公司 MVP | 0.3 | 71:18:11 | 有基本规范,灵活优先 |
| 中型互联网公司 | 0.5 | 65:20:15 | 有代码规范,有审查流程 |
| 金融/医疗企业 | 0.8 | 56:23:21 | 强合规要求,人主导决策 |
| 国企/央企核心系统 | 0.9 | 53:24:23 | 规范极严,文档驱动 |
2.3 场景复杂度 × 约束强度的二维矩阵
场景复杂度 低(单表CRUD) 高(13表联查报表) ┌─────────────────┬─────────────────┐ 高约束 │ 6:3:1 │ 4:3:3 │ (金融) │ 生成器做骨架 │ 人主导设计 │ │ 人适配规范 │ AI辅助SQL │ │ AI检查合规 │ 生成器实现 │ 约束强度 ├─────────────────┼─────────────────┤ 低约束 │ 8:1:1 │ 6:2:2 │ (创业) │ 几乎全自动 │ 生成器出骨架 │ │ 人只做确认 │ AI辅助复杂SQL │ │ │ 人确认优化 │ └─────────────────┴─────────────────┘三、SimpleDAO 生成器的"确定性 70%"包含什么?
以一张cha_channel渠道表为例,生成器 5 秒内输出11 个文件:
| 文件 | 内容 | 扩展点设计 |
|---|---|---|
Channel.java | Entity + @Table + @Id + @Schema | @Exclude 标记非持久化字段 |
ChannelCond.java | 条件类 + addCondition() | 注释预留 notIn/自定义条件 |
ChannelDao.java | 空类继承 BaseDao | 注释预留联表 SQL 模板 |
ChannelService.java | 标准 CRUD + 导入导出 | 注释预留复杂业务方法 |
ChannelController.java | REST API + Swagger 注解 | 注释预留唯一性校验 |
ChannelVO.java | 继承 Channel 的空类 | 联表时添加扩展字段 |
ChannelExcel.java | Excel 导出专用 VO | 独立控制列宽/列序/敏感字段 |
MockMvcTestChannel.java | 接口测试模板 | 方法级开关,按需启用 |
ChannelDialog.vue | 新增/编辑对话框 | dialogMix mixin 封装标准行为 |
ChannelList.vue | 不分页列表页 | pageMix mixin 封装标准交互 |
ChannelPage.vue | 分页列表页 | 完整分页 + 条件折叠 + 批量操作 |
11 个文件,100% 确定性输出,0 Token 成本,< 1 秒完成。
扩展点设计哲学:注释即文档,取消注释即扩展
// ChannelCond.java:注释预留的扩展条件@OverrideprotectedvoidaddCondition(){and("status =",status);in("channel_id",channelIds);/* 自定义条件↓ */// notIn("channel_id", channelIdsNot); // ← 需要时取消注释// add("AND create_time >= ?", startTime); // ← 需要时添加}四、AI 的"不确定性 20%":应该做什么?
AI 不做"生成"——生成是生成器的事。AI 做"建议"——建议是人做决策的依据。
场景 1:联表 SQL 设计辅助
// 生成器输出:单表 DAO(注释预留联表扩展)@RepositorypublicclassChannelDaoextendsBaseDao<Channel>{// private final static String SQL = "...";}// 人的输入:"渠道表需要关联用户表查创建人姓名,关联部门表查部门名称"// AI 辅助生成:privatefinalstaticStringSQL=""" SELECT t.*, u.name creator_name, d.dept_name FROM cha_channel t LEFT JOIN sys_user u ON t.create_by = u.user_id LEFT JOIN sys_dept d ON u.dept_id = d.dept_id """;// 人的确认:字段名正确?索引存在?性能可接受?场景 2:复杂条件逻辑设计
// 生成器输出:标准条件@OverrideprotectedvoidaddCondition(){and("status =",status);and("channel_code LIKE",channelCode,3);}// 人的输入:"需要查某个时间范围内、特定省份、且状态为已审核的渠道"// AI 辅助建议:add("AND create_time >= ?",startTime);add("AND create_time <= ?",endTime);add("AND province_code IN ",provinceCodes);and("status =",(byte)2);// 已审核状态// 人的确认:业务语义正确?参数命名规范?场景 3:性能优化与 Bug 定位
// 人写的 SQL:SELECTt.*FROMcha_channel tWHEREt.province_code=?ANDt.status=?// AI 审查建议:"province_code 和 status 的联合索引可能缺失, 建议:CREATEINDEXidx_province_statusONcha_channel(province_code,status);预估查询性能提升:从200ms 降至5ms"// 人的决策:是否创建索引?是否有写入性能影响?AI 不做"生成",做"建议";人做"确认"与"决策"。
五、人的"核心 10%":不可替代的决策
5.1 架构选型决策
AI 建议:"可以用 JPA 的 @ManyToOne 关联" 生成器默认:单表 CRUD 人的决策: · 这个场景是否需要联表?→ 是/否 · 联表频率高吗?→ 高则生成器预留 SQL,低则手写 · 性能要求?→ 高则原生 SQL,低则框架封装 · 团队能力?→ 强则 SQL-First,弱则 ORM 兜底5.2 业务规则确认
// AI 生成的校验逻辑:if(channelCode.startsWith("CH")){...}// 人的确认:"渠道编号必须以 'CH' 开头"是业务规则还是技术约束? → 业务规则:写入Service层校验,需产品确认 → 技术约束:写入数据库CHECK约束,需DBA确认5.3 性能基线设定
AI 说:"这个查询 100ms 算快" 生成器不 care 性能,只保证正确性 人的决策: · 接口 SLA 是多少?→ 50ms / 100ms / 500ms? · 数据量预期?→ 万级 / 百万级 / 亿级? · 是否需要缓存?→ Redis / 本地缓存 / 不缓存? · 分库分表策略?→ 现在做 / 预留扩展 / 不做AI 负责算出"怎么走最快",生成器负责"把路修好",而只有你知道"这条路通往哪里,以及该不该修"。
技术决策权,从来没有、也永远不会从人手里滑落。
六、防止 AI 屎山:范式层面的减法,不是代码层面的审查
传统做法的困境:AI 生成 → 人审查 → 改 AI 的代码
AI 生成 MyBatis XML(500 行) ↓ 人审查发现 10 个问题(ResultMap 错误、OGNL 语法、标签嵌套...) ↓ 改完 10 个问题,引入 3 个新问题(标签未闭合、别名冲突...) ↓ 循环往复... ↓ 结果:屎山代码,技术债务爆炸,审查成本 > 重写成本SimpleDAO 做法:范式约束 → AI 在约束内发挥
前提:SQL-First 范式已定义 · 单表:继承 BaseDao<T>,零代码 · 联表:写原生 SQL,page/list/field/row 统一 API · 条件:BaseCondition.add() 方法族,不分单表联表 · 结果:BeanPropertyRowMapper 自动映射 · 禁止:XML、OGNL、Criteria API、JPQL、DSL AI 在约束内工作: · 不会生成 XML(范式禁止) · 不会生成 Criteria API(范式禁止) · 不会生成 JPQL(范式禁止) · 不会生成 JOOQ DSL(范式禁止) · 只能生成:SQL 字符串 + Java 方法调用 结果:AI 的"创造性"被范式约束在可控范围内 输出即最终代码,无需审查修正防止 AI 写出屎山代码的唯一方法:不是事后审查 AI 的输出,是事前限制 AI 的输入空间。
七、SimpleDAO 在 AI 时代的三重成本优势
7.1 训练成本:压缩到零
| 框架 | AI 需要学习的上下文 | Token 消耗 |
|---|---|---|
| MyBatis | XML 结构 + OGNL 表达式 + ResultMap 语法 + 拦截器机制 | 5000+ |
| JPA | Entity 注解 + Criteria API + JPQL 语法 + Session 机制 | 4000+ |
| JOOQ | DSL API + 代码生成器配置 + 类型系统 | 6000+ |
| SimpleDAO | SQL 语法(AI 已内置)+ 3 个方法(add/and/in) | < 500 |
SimpleDAO 的训练成本趋近于零,因为 SQL 是 AI 的"母语"。
7.2 生成成本:本地执行,零 Token
MyBatis + AI: 生成 Entity(500 Token) 生成 Mapper XML(1500 Token) 生成 Service(800 Token) 生成 Controller(800 Token) 总计:3600 Token SimpleDAO + 生成器: 11 个文件,本地 Freemarker 模板替换 总计:0 Token,< 1 秒7.3 持续交互成本:指数级下降
MyBatis + AI: 第一轮:生成 XML(3000 Token) 发现问题:ResultMap 字段映射错误 第二轮:修正 XML(3000 Token) 发现问题:OGNL 表达式语法错误 第三轮:修正 OGNL(3000 Token) 发现问题:association 标签嵌套错误 ... 总计:9000+ Token,3+ 轮交互,20+ 分钟 SimpleDAO + AI: 第一轮:生成 SQL 字符串(500 Token) 发现问题:字段别名错误 第二轮:修正 SQL(500 Token) 确认无误 总计:1000 Token,2 轮交互,3 分钟人与 AI 的持续交互成本,SimpleDAO 是 MyBatis 的 1/5 ~ 1/10。
八、动态比例的实践路径
路径一:低约束团队(创业/原型)→ 7:2:1 起步
步骤 1:生成器 5 秒出全套代码(70%) 步骤 2:AI 辅助复杂 SQL 设计(20%) 步骤 3:人确认业务规则 + 性能基线(10%) 目标:1 天搭出可运行的管理系统路径二:中约束团队(成长型公司)→ 逐步推向 6:3:1
步骤 1:基于生成器代码,补充团队规范 步骤 2:AI 辅助代码审查,确保规范合规 步骤 3:人主导架构决策,生成器 + AI 执行 目标:规范与效率的平衡路径三:高约束团队(金融/医疗)→ 5:3:2 深耕
步骤 1:人制定详细规范文档(50%) 步骤 2:基于规范定制生成器模板(30%) 步骤 3:AI 辅助规范检查 + 复杂场景设计(20%) 目标:合规优先,效率不落后九、结语:范式即约束,约束即自由
“AI 特别有用,但它不应该抢传统代码生成器的活。”
这不是保守,这是工程理性:
- 生成器做确定性映射(表 → 代码),零成本、100% 正确、可重复
- AI 做不确定性探索(设计建议、Bug 定位),高价值、需验证、辅助决策
- 人做不可替代决策(架构、规则、责任),核心、最终把关、承担后果
SimpleDAO 的 SQL-First 范式,为 AI 时代提供了一个"约束框架":
- 不是限制 AI 的能力,是限制 AI 的"犯错空间"
- 不是替代人的决策,是释放人的创造力
- 不是否定其他框架,是证明"简单可以更有力量"
动态比例的核心洞察:
约束强度决定分工比例,场景复杂度决定交互深度,人的控制能力决定最终质量。
在这个范式下:
- AI 不会生成 XML 屎山,因为范式禁止 XML
- AI 不会生成 Criteria API 灾难,因为范式禁止 Criteria
- AI 不会生成 JOOQ DSL 迷宫,因为范式禁止 DSL
- AI只能生成 SQL 字符串 + Java 方法调用——这是 AI 最擅长、人最容易审查、数据库最直接执行的形式
7:2:1 或 5:3:2,不是选择,是结果。选择 SimpleDAO,选择让 AI 在正确的边界内发挥。
AI 万能论是片面的——它看到了 AI 的"可能性",却忽略了 AI 的"不可控性"和"高昂的持续成本"。
生成器 + AI + 人 = 工程理性的三角结构,缺一不可。
参考与试用
- 核心框架源码:https://gitee.com/gao_zhenzhong/simple-dao
- 系统底座:https://gitee.com/gao_zhenzhong/simple-dao-starter
- 代码生成器:https://gitee.com/gao_zhenzhong/simple-dao-coder
- 实战案例:https://gitee.com/gao_zhenzhong/simple-dao-demo
