Mybatis中#和$的区别
程序员文章站
2022-07-14 09:26:09
...
preparestatement和statement
再看之前,我们先来回顾preparestatement和statement之间的区别
先来看下PrepareStatement执行Sql的代码:
String sql = “select * from user where user_id=?”;
PreparedStatement pstmt = con.prepareStatement(sql);
pstmt.setString(1, “1001”);
ResultSet rs = pstmt.executeQuery();
因为PreparedStatement对象会预编译sql模版。在以后执行相同的语句模版只需要传参给他就可以重复执行,而不需要在进行编译.不仅提升了效率而且有效的防止了sql注入
#和$
在mybatis中,#和$的区别你可以理解为是PrepareStatement和StateMent的区别
我们来看这样的一个SQL语句
<select id="select" resultType="com.alibaba.fastjson.JSONObject">
select * from food where name = #{name}
</select>
@Test
void contextLoads() {
List<JSONObject> list = mapper.select(" '菜'or 1=1");
System.out.println(list.size());
}
这是最后发送的sql,获得正确的结果值
select *
FROM food
WHERE name = ' '菜' or 1=1';
再看这一组SQL
<select id="select2" resultType="com.alibaba.fastjson.JSONObject">
select * from food where name = ${name}
</select>
@Test
void contextLoads2() {
// 这个测试 会出错
List<JSONObject> list = mapper.select2("菜 or 1=1");
System.out.println(list.size());
}
下面是发送的sql,我们可以看到他直接name=菜的时候没有给我们添加字符串的引号。然后报错了,我们给加上``
下面的语句,最终发送的sql如下,导致了sql注入,or 1=1 变成了一个条件
@Test
void contextLoads2() {
List<JSONObject> list = mapper.select2(" 'c菜' or 1=1");
System.out.println(list.size());
}
${}使用场景
在我们需要排序的时候,我们一般使用${},由于#{}会帮我们加上引号,如果我们字段有 ‘stars’ 和 stars 这样的字段,而我们想要按照stars排序,如果使用#{}最后就会按照’stars’来排序了。
总结
1 、#{}是预编译处理,传入的参数最后会帮我们加上引号
2 ${},会有sql注入风险,传入的参数直接是字符串拼接,不会帮我们加上引号,导致参数可能变成查询条件