MyBatis中$与#的区别
1.问题描述
在mybatis的动态传参中, 我们可以私用#{},传递参数,也可以使用${}传递参数, 他们有什么差别呢?
如果在mybatis中的sql语句,使用的是in条件查询,则使用${}时会报错,这又是为什么呢?
2.举例说明
2.1. UserDao接口的方法
//根据字符串usernames,查询所有的User信息 public List<User> findByNames(@Param("usernames") String usernames) throws Exception;
2.2. 调用该方法
public class MybatisTest { @Test public void test01() throws Exception { InputStream is = Resources.getResourceAsStream("SqlMapconfig.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); SqlSession sqlSession = sqlSessionFactory.openSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); //假设参数是 'lucy','tom' String usernames = "'lucy','tom'"; List<User> list = userDao.findByNames(usernames); System.out.println(list); } }
2.3.配置(映射)文件中的配置
2.3.1.使用#{}
① 修改xml设置
<mapper namespace="com.itheima.dao.UserDao"> <!--根据字符串usernames,查询所有的User信息--> <select id="findByNames" resultType="com.itheima.domain.User" > select * from user where username in (#{usernames}) </select> </mapper>
② 执行删除test01()测试方法
③ 查看执行日志
DEBUG *** ==> Preparing: select * from user where username in (?) DEBUG *** ==> Parameters: 'lucy','tom'(String) DEBUG *** ==> Total: 0
④ 结论
#{} 预编译完成后, 变成了占位符?, 可以预防sql攻击
2.3.2 使用${}
① 修改xml设置
<mapper namespace="com.itheima.dao.UserDao"> <!--根据字符串usernames,查询所有的User信息--> <select id="findByNames" resultType="com.itheima.domain.User" > select * from user where username in (${usernames}) </select> </mapper>
② 执行删除test01()测试方法
③ 查看执行日志
<mapper namespace="com.itheima.dao.UserDao"> <!--根据字符串usernames,查询所有的User信息--> <select id="findByNames" resultType="com.itheima.domain.User" > select * from user where username in (${usernames}) </select> </mapper>
② 执行删除test01()测试方法
③ 查看执行日志
DEBUG *** ==> Preparing: Preparing: select * from user where username in ('lucy','tom') DEBUG *** ==> Parameters: DEBUG *** ==> Total: 2 [User{id=1, username='lucy', password='123'}, User{id=2, username='tom', password='123'}]
④ 结论
${} 会单纯的把参数值, 替代到sql语句对应位置上边. 不能预防sql攻击
3.补充
3.1 ${}的场景
- 作为in条件时,
- 参数为int类型并且数据库中字段的类型是number,
- 在sql语句中, 实现动态表名
- order by ${},动态排序字段
3.2 ${}的缺点(严重)
${}不能预防sql攻击
例设:
sql语句: select * from ${tablename}
参数值: product; drop product;
那么你的表数据就会被无声无息的干掉了。