#是预处理而$是直接替换
Mybatis在处理#{}时,会将SQL中的#{}替换成占位符?,再使用preparedStatement的set方法来赋值。
而Mybatis在处理 时,是将 {}时,是将 时,是将{}直接替换成变量的值
我们分别使用#{}和${}来查询userinfo表中名字叫admin的人
@Mapper
public interface UserMapper {Userinfo selectByName(@Param("username") String username);
}
<?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.example.demo.mapper.UserMapper"><select id="selectByName" resultType="com.example.demo.entity.Userinfo">select * from userinfo where username=#{username}</select>
</mapper>
使用单元测试:
@Test
void selectByName() {String name = "admin";Userinfo userinfo = userMapper.selectByName(name);System.out.println("用户信息:" + userinfo);
}
将#{}变成${}
${}存在sql注入的风险
例如登入场景,需要输入用户名和密码,如果使用${}就存在sql注入的风险。
什么是sql注入
SQL注入应用程序对用户输入数据的合法性没有判断或者过滤不严,攻击者利用SQL语法,拼接上一些特殊的sql语句,欺骗MySQL执行一些非授权的任意查询。最经典的sql注入就是' or 1='1"
<select id="login" resultType="com.example.demo.entity.Userinfo">select * from userinfo whereusername='${username}' and password = '${password}'
</select>
得到的结果如下:
也就是使用${}通过直接替换到sql语句中,是直接当作SQL语句的一部分,替换进去的是依据SQL语法可以实现拆分使用,而使用#{}通过占位符,把传进去的参数当作一个整体使用。
${}的使用场景
在开发中大部分是使用#{},但存在即合理。当我们传递的参数是SQL关键字时,使用${}。
例如,淘宝中价格从高到低需要传递参数desc,此时不能使用#{},不然会将desc认为是string类型。
注意:在使用${}时,传过来的参数一定是可枚举的,要经过检查才能使用