最近公司在业务开发中大力推行 AI 辅助写代码,作为一线开发者,我对这种新工具并不抵触。毕竟在重复且标准化的编码场景里,AI 确实能展现出高效的一面 —— 它往往能快速完成70 分的基础工作,把我们从机械的代码编写中解放出来,节省下不少时间。但真正考验人的,恰恰是剩下那30 分的细节排查与优化,这不,我刚在 AI 生成的动态 SQL 上栽了个 “隐蔽的坑”。

一、AI 生成的 “看似无错” 的 SQL

当时我需要编写一段 MyBatis 动态 SQL,用于根据前端传入的多组参数过滤数据,便直接让 AI 生成了核心逻辑。AI 给出的代码条理清晰,对每个参数都做了非空判断,初看完全符合常规写法:

<if test="account != null and account != ''">    AND account = #{account,jdbcType=VARCHAR}</if><if test="employeeConfirmStatus != null and employeeConfirmStatus != ''">    AND confirm_status = #{employeeConfirmStatus,jdbcType=VARCHAR}</if><if test="evaluateMonthStart != null and evaluateMonthStart != ''">    AND evaluate_month >= #{evaluateMonthStart,jdbcType=VARCHAR}</if><if test="evaluateMonthEnd != null and evaluateMonthEnd != ''">    AND #{evaluateMonthEnd,jdbcType=VARCHAR} >= evaluate_month</if>

二、联调时出现的 “诡异现象”

代码部署后,功能联调阶段却发现了异常,具体表现如下:

  • 异常场景:当前端传入 employeeConfirmStatus=0(代表 “未确认” 状态)时,查询结果返回所有数据,完全未按状态过滤;

  • 正常场景:当传入 1(已确认)或 2(已驳回)时,过滤逻辑正常生效,能精准筛选出对应状态的数据。

为定位问题,我反复核对了以下 3 个关键环节,均未发现异常:

  1. 前端传参格式:确认参数为纯数字类型,无多余字符串或特殊符号;

  2. 后端接收逻辑:通过日志打印确认参数绑定正常,无类型转换失败或参数丢失;

  3. 数据库字段类型:confirm_status 字段定义为 int 类型,与后端参数类型完全匹配。

三、排查:MyBatis 的 “隐性规则” 是关键

排除了传参、接收、存储三个环节后,我将目光重新聚焦到 AI 生成的 SQL 逻辑上,最终锁定问题核心 ——test=“employeeConfirmStatus != null and employeeConfirmStatus != ‘’” 这一判断条件,其背后隐藏着 MyBatis 动态 SQL 的重要特性:

MyBatis 对数字类型的隐式判断规则

若 标签中判断的参数为数字类型(如 Integer、int、Long 等),MyBatis 在解析 test 表达式时,会将「数字 0」与「空字符串’'」视为逻辑等价

具体到本次场景:当 employeeConfirmStatus=0 时,employeeConfirmStatus != ‘’ 会被解析为 false,导致整个 条件不成立,AND confirm_status = 0 这一过滤条件未被拼接进 SQL,最终查询出所有数据。

而当参数为 1、2 时,由于数字 1、2 与空字符串’'不满足 “等价逻辑”,employeeConfirmStatus != ‘’ 会返回 true,结合 employeeConfirmStatus != null 的判断,整个 条件成立,过滤逻辑正常执行。

这也暴露了 AI 的局限性:它仅能套用 “参数非空判断” 的通用模板,却无法结合 MyBatis 框架的隐性规则做针对性调整,对 “数字类型参数特殊处理” 这类细节缺乏感知。

四、优化方案:针对数字类型调整判断条件

明确问题根源后,优化方案便十分清晰:对于 employeeConfirmStatus 这类数字类型参数,只需保留「非 null 判断」,删除「非空字符串判断」,避免 MyBatis 的隐式逻辑干扰。优化后的完整 SQL 如下:

<if test="account != null and account != ''">    AND account = #{account,jdbcType=VARCHAR}</if><!-- 优化点:数字类型参数仅需判断非null,删除 != '' 的多余判断 --><if test="employeeConfirmStatus != null">    AND confirm_status = #{employeeConfirmStatus,jdbcType=VARCHAR}</if><if test="evaluateMonthStart != null and evaluateMonthStart != ''">    AND evaluate_month >= #{evaluateMonthStart,jdbcType=VARCHAR}</if><if test="evaluateMonthEnd != null and evaluateMonthEnd != ''">    AND #{evaluateMonthEnd,jdbcType=VARCHAR} >= evaluate_month</if>

优化后重新联调,传入 employeeConfirmStatus=0 时, 条件正常成立,SQL 成功拼接过滤逻辑,查询结果精准匹配 “未确认” 状态的数据,问题彻底解决。

五、反思:AI 辅助开发的 “边界感”

这次踩坑经历,让我对 “AI 辅助开发” 有了更理性、更务实的认知,也总结出 3 点核心思考:

  1. AI 的核心优势:效率提升

在标准化、重复性强的开发场景(如基础 SQL 编写、简单 CRUD 接口实现、文档注释生成等)中,AI 能快速输出可用的基础代码,帮开发者减少机械劳动,将精力聚焦到更复杂的业务逻辑上。

  1. AI 的明显短板:细节缺失

AI 对框架隐性规则(如 MyBatis 的参数判断逻辑)、业务特殊场景(如自定义状态码映射)、代码健壮性要求(如异常边界处理)的感知能力不足,无法替代开发者对技术栈的深度理解和对业务的精准把控。

  1. 开发者的核心价值:守住 “30 分细节”

目前阶段,AI 能完成 “70 分的基础工作”,但决定代码质量的 “30 分细节”—— 漏洞排查、场景适配、性能优化等,仍需依赖开发者。开发者的核心价值,在于成为 AI 输出的 “校验者” 和 “优化者”,而非被替代的 “执行者”。

显然,AI 要成为真正 “可靠的开发伙伴”,还有很长的路要走;而我们开发者,在享受 AI 带来的便利时,更需保持对代码的敬畏心 —— 毕竟一行小小的判断逻辑,就可能决定功能的成败,甚至影响系统的稳定性。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐