sp:Mybatis #{} 和 ${}的区别

区别

简单说,#{}是经过预编译的,而${}是未经过预编译的

#{}

为了说明,建立简单的表test如下:
+——-+————-+——+—–+———+—————-+
| Field | Type | Null | Key | Default | Extra |
+——-+————-+——+—–+———+—————-+
| id | int(11) | NO | PRI | NULL | auto_increment |
| value | varchar(20) | YES | | NULL | |
+——-+————-+——+—–+———+—————-+

预编译过程:

String sql = "select * from t where vlaue = ?";
PreparedStatement st = con.prepareStatement(sql);
st.setString(1, "id");

对于查询:select * from t where value = #{value}
想象Mybaits会如何做?
1 处理#{}部分为?
2 预编译语句
3 设置预编译语句中的?为#{}的值
如果要查询value是xxx的行的话,直接将#{value}设置为xxx即可

${}

${}不处理为预编译,而是字符串拼接
对应的查询:select * from t where value = ${value}
Mybatis会如何做呢?
因为只做字符串拼接,${value}的值为xxx的情况下,拼接处的sql语句为,select * from t where value = xxx,这条语句在数据库是不能执行的,能够执行的语句是select * from t where value = 'xxx'

#{}、${}转换

了解了以上,如果仍要用${}做查询如何做呢?
将语句处理为select * from t value = '${value}'即可,也就是加上引号,有一些数值类型是不需要引号也可以查询的,这里不做考虑,考虑更一般的情况,这样的话得到的效果和${}一致,区别在于是否预编译。
所以说,凡是能够使用#{}的地方都可以用${}替换,但是反过来不成立,例如order by,因为order by要传入的一定是不带引号的列名,所以无法使用#{},只能使用${},其它group by,等等只要与表有关而与值无关的元素都是必须不能带引号,而只能使用${},再举个例子的话,如group by。

最佳实践

能使用#{}的地方,都不要使用${},因为未经过预编译,直接拼接sql的${}存在sql注入的安全型问题。

你可能感兴趣的:(mybatis)