1,在單個入參的情況下,mybatis不做任何處理,#{參數名} 即可,甚至連參數名都可以不需要,因為只有一個參數,或者使用 Mybatis的內置參數 _parameter。
2,多個入參:
接口方法定義:public Employee getEmpByIdAndName(Integer id,String name);
取值:#{id},#{name}
mybatis拋出異常:org.apache.ibatis.binding.BindingException:Paramter 'id' not found Available parameters are [1,0,param1,param2]
原因如下:
Myabtis會特殊處理多個參數,多個參數會被封裝成一個Map(key:param1...paramN),或者根據參數索引獲取也可以(從0開始),#{param1...paramN}就是從map中獲取指定的key的值。
3,命名參數,明確指定多個參數被封裝成Map的可以,在方法入參上使用 @Param("id") 注解。#{id}取值id的值了。
public Employee getEmpByIdAndName(@Param("id")Integer id,@Param("name")String name);
4,POJO,如果多個參數正好是我們業務邏輯的數據模型,可以直接傳入POJO,#{屬性名},即可取出POJO的屬性值了。
public Employee getEmpByIdAndName(Employee emp);
5,Map<String,Object>,如果多個參數不是業務邏輯的數據模型,沒有對應的pojo,為了方便,可以傳入一個Map。#{key},取出Map中對應的值。
public Employee getEmpByIdAndName(Map<String,Object> map);
6,TO,如果多個參數不是業務邏輯的數據模型,但是要經常使用(比如分頁對象),推薦編寫一個TO(Transfer Object)數據傳輸對象。
===============================入參為集合====================================
public Employee getEmp(@Param("id")Integer id,String lastName);
取值:id===>#{id/param1} lastName=#{param2}
public Employee getEmp(Integer id,@Param("e")Employee emp);
取值:id===>#{param1} lastName=#{param2.lastName/e.lastName}
###特別注意,如果單個入參的類型是為集合類型,也會特殊處理,也是把傳入的List或數組封裝在Map中。key:Collection(collection),如果是List還可以使用這個key(list),如果是數組key為array。
public Employee getEmpId(List<Integer> ids);
取值:取出第一個id的值。#{list[0]}
============================================================================================================
Mybatis參數值的獲取
#{}:可以獲取Map中的值或者POJO對象屬性的值;
${}:取值效果同上,但是有區別:
1,#{}是以預編譯的形式,將參數設置到SQL語句中;相當於使用原生的PreparedStatement;(防止SQL注入)
2,${}是以拼接字符串的形式,將參數直接拼接在SQL語句中;(會有安全隱患)
大多數情況下,都應該去使用#{}取值;
比如分表:按照年份分表拆分,一年一張財務表。
select * from ${year}_工資表,表名是沒有辦法預編譯的。
select * from emp order by ${name} ${age},排序也不支持占位符。
#{}:更為豐富的用法,可以指定參數的類型,類型如下:
1,javaType,jdbcType,mode(存儲過程),numericScale,
2,resultMap,typeHandler,jdbcTypeName,expression(未來准備支持的功能)
jdbcType通常需要在某種特定的條件下被設置:
1,在數據為null的時候,有些數據庫可能不能識別Mybatis對null的默認處理,比如Oralce環境下會報錯。
2,JdbcType OTHER 無效類型:因為Mybatis對所有的null都映射的是原生Jdbc的OTHER類型,Oracle不能正確處理。(參見 org.apache.ibatis.type.JdbcType 枚舉類)
3,Oracle環境下應該這樣取值:#{email,jdbcType=NULL}
由於Mybatis的全局配置中,jdbcTypeForNull=OTHER,Oracle不支持,直接更改全局配置 jdbcTypeForNull=NULL 。(Settings標簽下配置)
===============================結合源碼,查看Mybatis如何處理入參====================================
1,首先我們的Mapper接口對象是一個代理對象(org.apache.ibatis.binding.MapperProxy<T>,它實現了java提供InvocationHandler接口)

2,被調用的Mapper代理對象的方法,被抽象成為 org.apache.ibatis.binding.MapperMethod 類型的對象,執行其 execute() 方法。它會判斷方法的是insert,update,delete還是select。

3,最后調用MapperMethod對象的 convertArgsToSqlCommandParam(args) 方法將入參轉換成一個Map。

①獲取每個標注了 @Param 注解的參數的param值。然后復制給name。
②每次解析一個參數,給map中保存一個信息(key:參數索引,value:name的值)。
name的值:
標注了@param注解,注解的值。
沒有標注:
1,全局配置:useActualParamName(需要jdk 1.8),name=入參參數名。
2,name=map.size();相當於元素的索引。
③如果入參為null,直接返回null。
④如果names只有一個元素,並且沒有 @Param 注解。直接names中的一個元素,直接返回。
⑤如果names有多個元素或者有 @Param 注解,遍歷names,names集合的value作為key;names集合的key又作為取值的參考args[0]:args[1,"tom"],重新放入一個新的Map對象中。
額外的將一個參數使用新的key:param1...paramN 保存到一個Map對象中。