当参数使用#{} 时,mybatis会有预编译的处理,将sql例如:select * from text where id = #{id} ,sql执行前,会先预编译为 select * from text where id = ? , 执行时,然后将?替换为实际的参数再进行执行。因为sql注入只能对编译过程起作用,所以这样的方式就很好地避免了sql注入的问题。同时也可以提高效率,执行相同的sql时已经预编译了,后面再执行就不会再编译。
mybatis是如何做到sql预编译的呢?其实在框架底层,是jdbc中的PreparedStatement类在起作用,PreparedStatement是我们很熟悉的Statement的子类,它的对象包含了编译好的sql语句。这种“准备好”的方式不仅能提高安全性,而且在多次执行一个sql时,能够提高效率,原因是sql已编译好,再次执行时无需再编译。
如果是将#{} 替换为${} 就无法阻止sql注入
在mybatis中,”${xxx}”这样格式的参数会直接参与sql编译,从而不能避免注入攻击。但涉及到动态表名和列名时,只能使用“${xxx}”这样的参数格式,所以,这样的参数需要我们在代码中手工进行处理来防止注入。