Mybatis(五)--原始碼分析傳入單個list引數和多個list引數寫法

環遊記發表於2018-03-24

強烈推薦一個大神的人工智慧的教程:http://www.captainbed.net/zhanghan

需求描述

      今天在做一個級聯刪除功能,許可權中刪除資源時,級聯刪除掉角色和資源繫結的資料。在學習mybatis的時候知道在dao層使用@param註解的原因是當傳入多個引數時可能會導致mybatis不知道引數對應關係,所以需要使用@param指定引數的別名,此次刪除就只有一個引數,心想沒必要加@param註解了,但是,報錯了。

問題描述

 

  • 介面如下:
 /**
     * 根據資源id刪除相關的角色資源繫結資料
     * @param applicationIds 資源ids
     * @return 受影響行數
     */
    int deleteByApplicationId(List<String> applicationIds);

 

  • 錯誤的實現程式碼如下:
<delete id="deleteByApplicationId">
        UPDATE tc_role_application
        SET is_delete =1
        WHERE application_id IN (
        <foreach collection="applicationIds" item="id" separator=",">
            #{id}
        </foreach>
        ) AND is_delete = 0

    </delete>

  報錯資訊如下:org.apache.ibatis.binding.BindingException: Parameter 'applicationIds' not found. Available parameters are [collection, list]

 

  •   正確的實現程式碼如下:
<delete id="deleteByApplicationId">
        UPDATE tc_role_application
        SET is_delete =1
        WHERE application_id IN (
        <foreach collection="list" item="id" separator=",">
            #{id}
        </foreach>
        ) AND is_delete = 0

    </delete>

原始碼分析

 

  1.   在傳入單個引數,引數型別為list或array或String型別時需要遵從如下規則

 

  • 如果傳入的是單個引數,且引數型別是一個List的時候,collection屬性值為list
  • 如果傳入的是單個引數,且引數型別是一個array的時候,collection屬性值為array
  • 如果傳入的是單個引數,且引數型別是一個String的時候,mapper中的寫法應該是#{_parameter}這樣的格式,例如,dao層介面中傳遞的引數是String id 那麼在mapper中需要寫成#{_id}

     2.  Mybatis原始碼

     在mybatis的jar包中,binding包下有MapperMethod這個類,其中execute方法針對不同的操作,根據不同的引數個數有不同的方案,當引數個數大於1時,會將引數封裝到一個map中,key值是@param註解對應的別名。

     上述程式碼中convertArgsToSqlCommandParam方法呼叫getNameParams方法:

總結

      mybatis為開發者封裝的非常的靈活,這些坑很簡單,但是不睬不知道呀!

相關文章