如下是 MyBatis 的映射文件。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zm.dao.CourseMapper">
<!--
多条件课程列表查询
-->
<select id="findCourseByCondition" parameterType="courseVo" resultType="course">
select * from course
<where>
<if test="courseName != null and courseName != ''">
and course_name like concat('%', #{courseName}, '%')
</if>
<if test="`status` != null and `status` != ''">
and `status` = #{status}
</if>
<if test="true">
and is_del != 1
</if>
</where>
</select>
</mapper>
启动了 Tomcat 服务器,使用 Postman 进行测试,使用了 log4j 输出 MyBatis 相关的 log。
当 status 为 1 时,无论有没有为 status 加反单引号,输出结果都是正确的:
02:02:18,119 DEBUG SpringManagedTransaction:87 - JDBC Connection [com.mysql.jdbc.JDBC4Connection@5fd1a13d] will not be managed by Spring
02:02:18,131 DEBUG findCourseByCondition:143 - ==> Preparing: select * from course WHERE course_name like concat('%', ?, '%') and `status` = ? and is_del != 1
02:02:18,176 DEBUG findCourseByCondition:143 - ==> Parameters: Vue.js 3.0 核心源码解析(String), 1(Integer)
02:02:18,233 DEBUG findCourseByCondition:143 - <== Total: 2
当 status 为 0 时,如果 <if test> 的 status 没有加反单引号,即便里面的 status 加了反单引号,输出结果是错误的:
<if test="status != null and status != ''">
and `status` = #{status}
</if>
02:06:47,190 DEBUG SpringManagedTransaction:87 - JDBC Connection [com.mysql.jdbc.JDBC4Connection@7d4a78] will not be managed by Spring
02:06:47,202 DEBUG findCourseByCondition:143 - ==> Preparing: select * from course WHERE course_name like concat('%', ?, '%') and is_del != 1
02:06:47,246 DEBUG findCourseByCondition:143 - ==> Parameters: Vue.js 3.0 核心源码解析(String)
02:06:47,282 DEBUG findCourseByCondition:143 - <== Total: 2
可以看到这时候的 <if test> 执行并没有通过,导致少追加了 status 的判断。
只有在 <if test> 的 status 加上反单引号,执行结果才是正确的:
<if test="`status` != null and `status` != ''">
and `status` = #{status}
</if>
02:11:24,352 DEBUG SpringManagedTransaction:87 - JDBC Connection [com.mysql.jdbc.JDBC4Connection@713af06d] will not be managed by Spring
02:11:24,365 DEBUG findCourseByCondition:143 - ==> Preparing: select * from course WHERE course_name like concat('%', ?, '%') and `status` = ? and is_del != 1
02:11:24,408 DEBUG findCourseByCondition:143 - ==> Parameters: Vue.js 3.0 核心源码解析(String), 0(Integer)
02:11:24,435 DEBUG findCourseByCondition:143 - <== Total: 0
整数类型的 isFree 也会出现这个问题,加上反单引号:
<if test="`isFree` != null and `isFree` != ''">
is_free = #{isFree},
</if>
由此可以推测出:整数类型转字符串类型后,0 代表空字符串的意思,加上反单引号可以把整数类型的 0 直接转为 字符 0。
同样道理,status 是整数类型,当它为 0 时,进行字符串转型会把它转为 null;加上反单引号就不会出错了。
但是加上反单引号却有另外一个问题,就是当 status 为 Integer 类型时, status 可以为 null,这时候使用反单引号进行整数类型转字符串类型会把 null 本身转为字符串 "null",从而导致判断出错。
所以,当 status 为 Integer 且可能为 null 时,最好是用以下方式解决:
<if test="status != null and status != '' or status == 0">
and `status` = #{status}
</if>
网友评论