之前不用MyBatis的时候,直接写JDBC会用到Statement和Preparestatement。PrepareStatement可以避免Statement的SQL注入问题,而避免的方法就是使用?
来当占位符,这里${}和#{}就是类似的情况。
下面举两个例子作为对比。
对于 select * from user where id=#{}
传入参数 1001
实际SQL select * from user where id='1001'
对于 select * from user where id=${}
传入参数 1001
实际SQL select * from user where id=1001
就像前面说的,我们使用PrepareStatement来防止SQL注入,这里也是使用#{}来防止SQL注入。
假如我们在程序中写这样的SQL
String sql = "select * where name= ' "+name+" ' "
传入参数 name = " 'or 1=1 '"
最终的SQL结果
select * where name= ' ' or '1=1'
用${}:
这样就能跳过查询条件(–是SQL的注释),从而直接得到所有结果。而使用PrepareStatement和#{}能避免这种情况,它们会将传入的参数变为字符串,直接加上引号。
用#{}:
但是如果使用order by、like以及传入表名就需要用到${},因为它们本身不能带有引号。
上面的说明,网上其他地方也都类似,下面是我进行测试时碰见的另一个问题。
我们在给MyBatis配置数据源时,要么直接在environment标签里写driver、url等参数,要么通过propert标签引入database.properties里的配置(也可以直接在properties标签里写属性)
mybatis-config.xml
databse.properties
UserMapper.java
假如我们在UserMapper.xml里写SQL,用到的变量名正好也是username1或者username2,也就是和properties标签里的属性名重复了,那么通过${username1}得到是优先是properties里的,而不是我们实体类User传递过来的。