Mybatis對映檔案Mapper.xml中#和$的區別
關於Mapper.xml對映語句中什麼時候用"#"什麼時候用"$",已經有很多人做過總結,我最近在寫專案時仍然遇到了一點問題,所以在這裡結合專案文件和案例,再做一下總結,也作為個人的筆記,在這裡再總結下。
一、先看一下在mybatis api中關於"#"和"$"的描述
1、"#"
圖 1來自於mybatis api “Mapper XML檔案”章節, 簡單來說"#"在編譯時使用"?"佔位符標記,可以有效防止引數注入,相當於我們使用JDBC操作時的PreparedStatement。
圖1
2、"$"
圖2同樣來自於mybatis api “Mapper XML檔案”章節,意思是直接把引數拼接到SQL中執行相當於JDBC操作時的Statement
圖2
二、結合案例具體說明"#"和"$" 的區別。
1、引數作為非SQL關鍵字傳遞
<insert id="addUser" parameterType="User">
insert into users values(default, ${username}, ${password}, ${photo});
</insert>
該語句執行報錯,通過日誌分析,
[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 id="addUser" parameterType="User">
insert into users values(default, "${username}", "${password}", "${photo}");
</insert>
日誌如下:
[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 id="addUser" parameterType="User">
insert into users values(default, #{username}, #{password}, #{photo});
</insert>
2、引數作為關鍵字傳遞,比如查詢條件全是由引數拼接的,只是用一條SQL,有時要按name列查,有時要按age列查
<select id="selectUser" parameterType="User" resultType="User">
select * from users where ${columnName} ${condition} #{columnValue}
</select>
SQL1:select * from users where username = "test";
SQL2:select * from users where userage like "%2";
因為列名和關係條件是關鍵字,是用"$",列值是非關鍵字,使用"#"。
三、總結
1、關鍵字作為引數,使用"$",兩邊不加""。
2、非關鍵字作為引數,使用"#"防注入。
其他情況優先使用"#"