主要原因就是,在映射文件中的SQL语句编写错误
<?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.itheima.mapper.EmpMapper">
<select id="list" resultType="com.itheima.pojo.Emp">
select *
from emp
where
<if test="name!=null">
name like concat('%',${name},'%')
</if>
<if test="gender != null">
and gender = #{gender}
</if>
<if test="start!=null and end!=null">
and entrydate between #{start} and #{end}
</if>
order by update_time desc
</select>
</mapper>
以上代码将中间部分,$占位符改为#改为:即可
<if test="name!=null">
name like concat('%',#{name},'%')
</if>
小结:
在MyBatis中,$
符号和#
符号都用于表示参数占位符,但它们之间有一些区别:
-
$
符号表示直接将参数值替换到SQL语句中,它不会对参数进行任何转义或过滤(可以理解为直接拼接的方式)。这可能导致SQL注入的风险,因此应该尽量避免使用$
符号。 -
#
符号表示将参数值作为预编译的SQL语句的一部分(通过传参方式),它可以有效防止SQL注入攻击。MyBatis会自动对参数进行转义和过滤,确保安全性。
一般使用#
符号作为参数占位符,因为它可以提供更好的安全性和灵活性。而$
符号应该尽量避免使用,以防止SQL注入攻击。
但是由于#符号不能出现在单引号内,因此在此时吗,需要使用$进行代替。
可以使用以下两种方法之一:
- 使用双引号代替单引号:将SQL语句中的单引号替换为双引号,然后在
#{}
中使用$
符号表示参数占位符。
<select id="findUserByName" resultType="com.example.User">
SELECT * FROM users WHERE name = "${name}";
</select>
- 使用转义字符:在
#{}
中使用\
字符对单引号进行转义,然后使用$
符号表示参数占位符。
<select id="findUserByName" resultType="com.example.User">
SELECT * FROM users WHERE name = \'${name}\';
</select>
MyBatis中#符号和$符号的存在差异:
#
符号解析为SQL时,会将形参变量的值取出,并自动给其添加引号。因此,#
符号在一定程度上可以防止SQL注入,增加安全性。然而,由于单引号在SQL语句中有特殊含义,所以在需要使用单引号的地方不能直接使用#
符号。
而${}
方式则无法防止Sql注入。当使用${}
方式传递参数时,如果参数值中包含单引号,那么需要在SQL语句中使用两个单引号来表示一个单引号。这是因为MyBatis会将${}
中的参数值直接替换到SQL语句中,而不会自动对单引号进行转义。
因此,在使用MyBatis时,推荐尽可能使用#
符号作为参数占位符,因为它更安全,能够避免SQL注入攻击。而在必须使用单引号的地方,可以通过转义字符或者使用双引号来代替单引号的方法来解决这个问题。