动态 SQL 的“调试难”主要是因为 SQL 是在运行时才拼出来的,不像静态 SQL 一眼就能看到。下面按常见场景 + 实用调试方法系统讲一下,基本能覆盖 90% 的情况。
不同技术栈,调试方式不一样:
| 场景 | 常见技术 |
|---|---|
| MyBatis | <if>/<choose>/<foreach> |
| JDBC / 原生代码 | 字符串拼接 SQL |
| Spring JPA | Specification、Criteria |
| 存储过程 | PL/SQL / T-SQL |
| 自己拼 SQL | String.format、StringBuilder |
下面重点讲 最常见、最坑的 MyBatis 动态 SQL。
在 application.yml / application.properties 中:
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
或者(推荐,配合日志框架):
logging:
level:
com.xxx.mapper: debug
执行后你会看到类似:
==> Preparing: SELECT * FROM user WHERE 1=1 AND age > ? AND name = ?
==> Parameters: 18(Integer), Tom(String)
✅ 这已经是“最终 SQL”了
? 替换成真实参数(人工还原)MyBatis 默认是 预编译 SQL + 参数占位符,你可以手动还原:
SELECT * FROM user WHERE age > 18 AND name = 'Tom'
⚠️ 注意:
System.out.println(userQuery);
或:
log.debug("query param: {}", userQuery);
确认:
null这是最实用的调试方式之一
如果这里就报错:
<script> + 注解方式时特别小心@Select("<script>
SELECT * FROM user
<where>
<if test='name != null'> AND name = #{name} </if>
</where>
</script>")
调试建议:
<if test="list != null"> 但 list 为空<if test="ids != null and ids.size() > 0">
✅ 正确写法
<if test="type == 'A'"> <!-- 错误 -->
✅ 正确:
<if test='type == "A"'>
或:
<if test="type.equals('A')">
AND / ORWHERE
<if test="name != null">AND name = #{name}</if>
✅ 用 <where> 标签:
<where>
<if test="name != null">AND name = #{name}</if>
</where>
System.out.println(sql);
❌ 错误:
"WHERE name = '" + name + "'"
✅ 正确:
"WHERE name = ?"
SHOW VARIABLES LIKE 'general_log';
SET GLOBAL general_log = ON;
SELECT * FROM pg_stat_activity;
90% 问题按这个流程都能解决
? 替换成真实值<if> 条件是否真的成立你可以直接贴:
我可以 直接帮你指出哪一行拼错了、为什么条件没生效。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。