6.4 常见问题与排错 本节摘要:故障排查的效率取决于两件事:取证手段是否常备,以及报错信息到故障点的映射是否烂熟。本节先备齐日志与插件两件取证工具,给一张高频故障速查表,再把全册踩过的坑编成一张从报错信息出发的决策树。 前几节分别处理"怎么做好",这一节处理"做坏了怎么查"。排错不走弯路的秘诀只有一个:从报错信息直接定位到检查点,而不是从头到尾把配置重读一遍。 先备取证工具 两件工具要在故障发生之前备好: DEBUG 日志一次取证能拿到三样东西:发出的完整 SQL(动态拼装后的最终文本)、实际传入的参数(JDBC 参数逐个打印)、返回行数(Total)。6.3 的 N 加一定位靠它,"参数没传对"还是"SQL 拼错了"的一步分诊也靠它。需要统计耗时或拦执行链时,5.
本节摘要:故障排查的效率取决于两件事:取证手段是否常备,以及报错信息到故障点的映射是否烂熟。本节先备齐日志与插件两件取证工具,给一张高频故障速查表,再把全册踩过的坑编成一张从报错信息出发的决策树。
前几节分别处理"怎么做好",这一节处理"做坏了怎么查"。排错不走弯路的秘诀只有一个:从报错信息直接定位到检查点,而不是从头到尾把配置重读一遍。
两件工具要在故障发生之前备好:
<!-- mybatis-config.xml:生产用 SLF4J 接日志框架,开发期可临时用 STDOUT_LOGGING --> <settings> <setting name="logImpl" value="SLF4J"/> </settings>
<!-- logback:把 Mapper 包开到 DEBUG,完整 SQL、参数、返回行数全部落盘 --> <logger name="com.example.mapper" level="DEBUG"/>
DEBUG 日志一次取证能拿到三样东西:发出的完整 SQL(动态拼装后的最终文本)、实际传入的参数(JDBC 参数逐个打印)、返回行数(Total)。6.3 的 N 加一定位靠它,"参数没传对"还是"SQL 拼错了"的一步分诊也靠它。需要统计耗时或拦执行链时,5.3 的计时插件是第二件取证工具。
| 报错/现象 | 根因 | 检查点 |
|---|---|---|
| BindingException: Invalid bound statement | 接口方法找不到对应 SQL | namespace 是否全限定名、id 是否对齐方法名、XML 是否在编译产物里(Maven resources 过滤常把 XML 弄丢) |
| Parameter 'xxx' not found | 参数名对不上 | 多参数是否加 @Param、单参数误用属性名取值(2.2 的装配规则) |
| 查询结果为 null(数据库有值) | 列名与属性名对不上 | 驼峰开关 mapUnderscoreToCamelCase 是否开启、resultMap 的 column 是否写对(3.1 的映射规则) |
| TooManyResultsException | selectOne 撞上多行结果 | 业务上确实只该有一行就查条件;否则改 selectList |
| 分页结果错位 | 分页参数与排序不稳定 | LIMIT 前必须有确定性 ORDER BY,页码从 0 还是 1 起要统一 |
| 数据"没保存" | 事务没提交 | 手动模式漏了 commit、Spring 里吞了异常(6.1 的失效清单) |

案例一:BindingException。启动正常、调用就炸。走决策树:执行期 → 开 DEBUG(SQL 都没打印就炸了,说明没到数据库)→ 检查点是绑定三要素:namespace 全限定名、id 与方法名、XML 是否进了 classpath。十有八九是 XML 没被 Maven 打进产物——查 target/classes 下的文件。
案例二:结果为 null。DEBUG 日志显示 SQL 正确发出、参数正确、Total: 1,但对象字段全空——问题锁定在映射层而非 SQL 层。检查驼峰开关与 resultMap 的 column 拼写;用了 select 星号的,检查列是否真的在返回集里。
案例三:数据"没保存"。程序无报错、表里没数据。检查事务:手动模式看有没有 commit;Spring 环境按 6.1 的失效清单过一遍——内部调用与非 public 方法是最常见的两个。
⚠️ 常见坑:别在生产开 STDOUT_LOGGING——它直接打控制台,量大且绕过日志框架的级别管控。生产环境用 SLF4J,并把 Mapper 日志级别控制在需要的范围内。
💡 关键直觉:MyBatis 的故障几乎都能归到四层之一——绑定层(方法到 SQL 的映射)、装配层(参数入)、映射层(结果出)、执行层(事务与连接)。报错先归层,再按层查点,比通读配置快一个量级。
排错树收拢完毕。最后一节走出工具间,站到版本与生态的坐标上看 MyBatis 的现在与去向。