关于Mapper.xml映射语句中什么时候用"#"什么时候用"$",已经有很多人做过总结,我最近在写项目时仍然遇到了一点问题,所以在这里结合项目文档和案例,再做一下总结,也作为个人的笔记,在这里再总结下。
1、"#"
图 1来自于mybatis api “Mapper XML文件”章节, 简单来说"#"在编译时使用"?"占位符标记,可以有效防止参数注入,相当于我们使用JDBC操作时的PreparedStatement。
2、"$"
图2同样来自于mybatis api “Mapper XML文件”章节,意思是直接把参数拼接到SQL中执行相当于JDBC操作时的Statement
1、参数作为非SQL关键字传递
insert into users values(default, ${username}, ${password}, ${photo});
该语句执行报错,通过日志分析,
[19:32:41.422] [DEBUG] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:139) ==> Preparing: insert into users values(default, test, 123456, c9ae464f-348d-491d-a162-a9624c99f73b);
[19:32:41.479] [DEBUG] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:139) ==> Parameters:
Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'test' in 'field list'
; bad SQL grammar []; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'test' in 'field list'] with root cause
从这里可以看到,这里直接把获取到的参数拼接到了SQL中,数据库把参数当成了列名,数据库字段设置的都是varchar类型,需要把列值加上"",方可执行成功,如下:
insert into users values(default, "${username}", "${password}", "${photo}");
日志如下:
[19:42:30.616] [DEBUG] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:139) ==> Preparing: insert into users values(default, "test", "123456", "85ec0040-46dc-4a92-b995-7ed84ece2f28");
[19:42:30.698] [DEBUG] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:139) ==> Parameters:
[19:42:30.755] [DEBUG] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:139) <== Updates: 1
或者把"$"改成"#"
insert into users values(default, #{username}, #{password}, #{photo});
2、参数作为关键字传递,比如查询条件全是由参数拼接的,只是用一条SQL,有时要按name列查,有时要按age列查
select * from users where ${columnName} ${condition} #{columnValue}
SQL1:select * from users where username = "test";
SQL2:select * from users where userage like "%2";
因为列名和关系条件是关键字,是用"$",列值是非关键字,使用"#"。
1、关键字作为参数,使用"$",两边不加""。
2、非关键字作为参数,使用"#"防注入。
其他情况优先使用"#"