mybatis中#和$的区别
前言
在原生的操作数据库的代码中,常常会用到PreparedStatement和Statement两个对象,其中PreparedStatement继承自Statement,这两个对象之间的区别之一就是PreparedStatement会对sql进行预编译处理,而Statement不会。有如下代码示例:
// 使用PreparedStatement对象 //定义sql语句,变量的位置用?号代替 String sql = "select user_id, user_name, user_age from user_info where user_id = ?"; //通过Connection得到预编译后的对象,相对于Statement这一步消耗很大,不过优势体现在后面,因为sql已经预编译过了 PreparedStatement ps = conn.preparedStatement(sql); //给PreparedStatement对象设值,sql中有几个?号就要设几个值,下标从1开始 ps.setInt(1, user.getUserId()); //ResultSet接收查询得到的结果集 ResultSet rs = ps.executeQuery(); //使用Statement对象 //定义sql语句,采用字符串拼接的方式 String sql = "select user_id, user_name, user_age from user_info where user_id = " + user.getUserId(); //通过Connection获取Statement对象 Statement stmt = conn.createStatement(); //ResultSet接收结果集 ResultSet rs = stmt.executeQuery();
在以上的代码中可以看到,PreparedStatement执行sql时会先将sql预编译,这时如果恶意插入一段sql语句(即SQL注入)也不会成功执行,但是在Statement中,sql是通过字符串拼接获取,所以如果插入的sql符合一定条件是会执行的,从而达到恶意攻击的目的。
区别
1、#{}是预编译处理,Mybatis在处理sql语句时,会将sql中的#{}符号替换成?,然后使用PreparedStatement的set方法来赋值,并且传入值后,会在值的两边加上单引号
2、${}是字符串替换,mybatis在处理sql语句时,会将sql中的${}符号直接替换成变量的值,同时,替换的值的两边不会加上单引号,所以可能会导致sql注入