MyBatis 傳參分析

傳入參數

MyBatis 容許兩種方式的使用:經過定義接口,或經過 SqlSession 調用命名空間。這二者的傳參方式不一樣,前者通過 MyBatis 處理後變爲後者。後者更直接,當須要傳入多個參數時要本身構建 Mapjava

當使用接口時,會執行如下步驟:sql

Object param = method.convertArgsToSqlCommandParam(args);
result = sqlSession.<E>selectList(command.getName(), param);

Object convertArgsToSqlCommandParam (Object[] args) 有如下規則:json

  • 傳入 null 或空數組,返回 null;
  • 沒有使用 @Param 註解,且數組裏只有一個對象,返回該對象;
  • 不然返回 Map<String, Object>

第三種狀況下,Map<String, Object> 的數據首先根據 paramsargs 裏取。params 是一個 Map<Integer, String>,存儲了形參的順序和名字,名字的規則是:數組

  • @Param 註解,使用註解的 value
  • 不然,使用形參順序

例如:ide

List<Entity> select(@Param("group") String groupName, Long offset, Integer limits);

對應的 params(使用 json 格式以便觀察):code

{
    "0": "group",
    "1": "1",
    "2": "2",
}

注意到只要不帶 @Param 註解,就須要使用下標了。xml

這尚未結束,爲了方便容許使用下標,MyBatis 還按 params 順序設置了另外一組值,使得輸出的結果相似於:對象

{
    "group": "xxx",
    "1": 0,
    "2": 20,
    "param0": "xxx",
    "param1": 0,
    "param2": 20,
}

固然了,若是你手動指定的參數名剛好爲 param<Index> 以致於跟這條規則重複了,那麼 MyBatis 會跳過已經存在的鍵。接口

無論是 selectOne 仍是 selectMap 方法,都是經過 selectList 執行查詢的,無論是 insert 仍是 delete 方法,都是經過 update 方法執行的。get

selectListupdate 中,對全部參數的都進行了統一的處理。

對於集合,默認使用 DefaultSqlSession::wrapCollection 處理:

private Object wrapCollection(final Object object) {
    if (object instanceof Collection) {
        StrictMap<Object> map = new StrictMap<Object>();
        map.put("collection", object);
        if (object instanceof List) {
            map.put("list", object);
        }
        return map;      
    } else if (object != null && object.getClass().isArray()) {
        StrictMap<Object> map = new StrictMap<Object>();
        map.put("array", object);
        return map;
    }
    return object;
}

使用參數

  • 標準處理(如 #{value}#{object.value}
  • 使用 OGNL 方式獲取值(如 ${orderby}
  • 使用在條件語句中(如 <if test="object.value != null">

這裏咱們注意到可使用複雜類型,因而咱們能夠寫出很是靈活的動態 SQL,好比:

<update id="update">
    UPDATE `Sample`
    <set>
        <if test="set.name != null">
            `name`=#{set.name},
        </if>
        <if test="set.value != null">
            `value`=#{set.value},
        </if>
    </set>
    <trim prefix=" WHERE " prefixOverrides="AND">
        <if test="where.id != null">
            AND `id`=#{where.id}
        </if>
        <if test="where.name != null">
            AND `name`=#{where.name}
        </if>
    </trim>
    ;
</update>
相關文章
相關標籤/搜索