${}和#{}的区别
- #{}是预编译处理。MyBatis在处理#{}时会将sql语句中的#{}替换成?,调用PreparedStatement的set()方法来赋值。能有效防止SQL注入,提高安全性。
- ${}是字符串替换。MyBatis在处理#{}时会将sql语句中的${}替换成变量的值,相当于直接拼接sql语句,可能发生SQL注入。
从JDBC来看
#{}
看SQL语句中使用#{}
运行项目后,查看打印的SQL信息,SSM如何配置SQL日志打印这里不说明,打印的日志如下:
可以看到其实使用#{}的处理与JDBC的预编译SQL语句相似,MyBatis在处理时将#{}替换成了?。
public boolean save(Account account) {
PreparedStatement preparedStatement = null;
int num = 0;
try {
Connection connection = JDBCUtils.getConnection();
String sql = "insert into account(name,money) values (?,?)";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, account.getName());
preparedStatement.setString(2, account.getMoney());
// 执行插入,返回受影响行数
num = preparedStatement.executeUpdate();
// 判断是否插入成功
return num > 0;
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.release(preparedStatement, connection);
}
return false;
}
${}
使用${}来放置参数
运行项目,查看打印的SQL日志信息:
发现直接是将变量替换成${},看上面的name字段,是字符串,明显该加引号,也没有处理,所以直接造成错误。
所以${}有点与JDBC的sql语句拼接类似。
public boolean save(Account account) {
PreparedStatement preparedStatement = null;
Statement statement = null;
int num = 0;
try {
Connection connection = JDBCUtils.getConnection();
String sql = "insert into account(name,money) values ('" + account.getName() + "'," + account.getMoney() + ")";
statement = connection.createStatement();
boolean execute = statement.execute(sql);
return execute;
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.release(preparedStatement, connection);
}
return false;
}
使用${}可能引起注入问题,所以${}的一般应用场景是动态传入表名或列名,不用来传递参数,所以优先考虑使用#{}。