Mybatis方法入參處理


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對象中。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM