Mapper.xml的SQL语句中的占位符${}和#{}
{}:预编译#{}在mybatis中,最后会被解析为?,其实就是Jdbc的PreparedStatement中的?占位符,它有预编译的过程,会对输入参数进行类型解析(如果入参是String类型,设置参数时会自动加上引号),可以防止SQL注入,如果parameterType属性指定的入参类型是简单类型的话(简单类型指的是8种java原始类型再加一个String),#{}中的变量名可以任意,如果入参类
#{}:预编译
#{} 在mybatis中,最后会被解析为?,其实就是Jdbc的PreparedStatement中的?占位符,它有预编译的过程,会对输入参数进行类型解析(如果入参是String类型,设置参数时会自动加上引号),可以防止SQL注入,如果parameterType属性指定的入参类型是简单类型的话(简单类型指的是8种java原始类型再加一个String),#{}中的变量名可以任意,如果入参类型是pojo,比如是Student类
public class Student{
private String name;
private Integer age;
}
那么#{name}
表示取入参对象Student中的name属性,#{age}
表示取age属性,这个过程是通过反射来做的,这不同于${}
,${}
取对象的属性使用的是OGNL(Object Graph Navigation Language)表达式。
${}:字符串拼接
${},一般会用在模糊查询的情景,比如SELECT * FROM student WHERE name like '%${name}%';
它的处理阶段在#{}之前,它不会做参数类型解析,而仅仅是做了字符串的拼接,若入参的Student对象的name属性为zhangsan,则上面那条SQL最终被解析为SELECT * FROM student WHERE name like '%zhangsan%';
而如果此时用的是SELECT * FROM student WHERE name like '%#{name}%'; 这条SQL最终就会变成
SELECT * FROM student WHERE name like '%'zhangsan'%'; 所以模糊查询只能用${},虽然普通的入参也可以用${},但由于${}不会做类型解析,就存在SQL注入的风险,比如
SELECT * FROM user WHERE name = '${name}' AND password = '${password}'
我可以让一个user对象的password属性为'OR '1' = '1,最终的SQL就变成了
SELECT * FROM user WHERE name = 'yogurt' AND password = ''OR '1' = '1',因为OR '1' = '1'恒成立,这样攻击者在不需要知道用户名和密码的情况下,也能够完成登录验证
另外,对于pojo的入参,${}中获取对象属性的语法和#{}几乎一样。
更多推荐
所有评论(0)