首先,像 MyBatis 的其他部分一樣,參數也可以指定一個特殊的數據類型。
#{property,javaType=int,jdbcType=NUMERIC}
像 MyBatis 的剩余部分一樣,javaType 通常可以從參數對象中來去確定,前提是只要對象不是一個 HashMap。那么 javaType 應該被確定來保證使用正確類型處理器。
NOTE 如果 null 被當作值來傳遞,對於所有可能為空的列,需要設置參數的jdbcType。你可以自己通過閱讀預處理語句的 setNull() 方法的 JavaDocs 文檔來研究這種情況。
為了以后定制類型處理方式,你也可以指定一個特殊的類型處理器類(或別名),比如:
#{age,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler}
盡管看起來配置變得越來越繁瑣,但實際上是很少去設置它們。
對於數值類型,還有一個小數保留位數的設置,來確定小數點后保留的位數。
#{height,javaType=double,jdbcType=NUMERIC,numericScale=2}
最后,mode 屬性允許你指定 IN,OUT 或 INOUT 參數。
如果參數為 OUT 或 INOUT,參數對象屬性的真實值將會被改變,就像你在獲取輸出參數時所期望的那樣。如果 mode 為 OUT(或 INOUT),而且 jdbcType 為 CURSOR(也就是 Oracle 的 REFCURSOR),你必須指定一個 resultMap 來映射結果集到參數類型。要注意這里的 javaType 屬性是可選的,如果左邊的空白是 jdbcType 的 CURSOR 類型,它會自動地被設置為結果集。
#{department, mode=OUT, jdbcType=CURSOR, javaType=ResultSet, resultMap=departmentResultMap}
MyBatis 也支持很多高級的數據類型,比如結構體,但是當注冊 out 參數時你必須告訴它語句類型名稱。比如(再次提示,在實際中要像這樣不能換行):
#{middleInitial, mode=OUT, jdbcType=STRUCT, jdbcTypeName=MY_TYPE, resultMap=departmentResultMap}
盡管所有這些強大的選項很多時候你只簡單指定屬性名,其他的事情 MyBatis 會自己去推斷,最多你需要為可能為空的列名指定 jdbcType。
#{firstName} #{middleInitial,jdbcType=VARCHAR} #{lastName}
字符串替換
默認情況下,使用#{}格式的語法會導致 MyBatis 創建預處理語句屬性並安全地設置值(比如?)。這樣做更安全,更迅速,通常也是首選做法,不過有時你只是想直接在 SQL 語句中插入一個不改變的字符串。比如,像 ORDER BY,你可以這樣來使用:
ORDER BY ${columnName}
這里 MyBatis 不會修改或轉義字符串。
NOTE 以這種方式接受從用戶輸出的內容並提供給語句中不變的字符串是不安全的,會導致潛在的 SQL 注入攻擊,因此要么不允許用戶輸入這些字段,要么自行轉義並檢驗。
3.1 #{}與${}
注意以下兩個符號的使用:
#{}(ibatis為:##):MyBatis創建預處理語句屬性從而設置安全的值(比如?)。常用作查詢條件的值,例如:where name=#{value}。
該參數可以指定一個確切的數據類型,例如: #{property,javaType=int,jdbcType=NUMERIC}.
${}(ibatis為:$$): MyBatis不會修改或轉義字符串,將會直接在SQL語句中插入一個不改變的字符串,常用於拼湊sql的實體部分,
例如:select * from ${tableName}