列表页多条件筛选,mapper.xml 里用得最多的就是 if 标签。mybatis if test 的写法本身不复杂,坑都藏在 test 表达式里,一个引号方向用错,接口直接抛 OGNL 异常,或者条件永远不生效,尤其是字符串判空,别照抄网上的模板,先看自己的参数类型。test 里也支持 and、or 这种英文写法,比符号直观,还不涉及转义。
<if test='status != null and status > 0'> and status = #{status} </if> <if test='name != null and name != ""'> and name like concat('%', #{name}, '%') </if>单字符字符串的比较坑
判断性别是不是 Y 这类单字符时,如果外层用双引号、里层用单引号,OGNL 会把单引号里的单个字符当成 char 类型,跟字符串比较永远不等,条件一直不生效,日志里还看不出问题。稳妥做法是外层单引号、里层双引号,团队里统一成一种风格,新人才不会来回踩。口诀记外单内双,贴错了一改就能验证。
XML 转义别偷懒
小于号在 XML 里是保留字符,test 里写 age < 18 必须转义,大于号可以不转,但顺手写成 > 更省心。忘了转义不是运行时才炸,是应用启动加载 mapper 时就报错,日志会指向 xml 的具体行列,定位不难。
几个实用习惯
- 多个 if 拼条件时外面套 where 标签,开头的 and 会自动处理,不用手写 1=1。
- test 里访问的是参数对象的属性,接口方法用 @Param 起了别名就按别名写。
- 判断集合别只判 null,加上 size() 大于 0 才稳,空集合进 in 查询直接报语法错。
- 复杂条件抽成 sql 片段复用,if 里再嵌 if 不要超过两层,不然半个月后自己都看不懂。
mybatis if test 的本质就是一段 OGNL 表达式,把引号方向、null 判断和转义这三件事写对,动态 SQL 绝大多数的坑都绕开了。