MyBatis 传参分析

传入参数

MyBatis 允许两种方式的使用:通过定义接口,或通过 SqlSession 调用命名空间。这两者的传参方式不同,前者经过 MyBatis 处理后变为后者。后者更直接,当需要传入多个参数时要自己构建 Map

当使用接口时,会执行以下步骤:

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

Object convertArgsToSqlCommandParam (Object[] args) 有以下规则:

  • 传入 null 或空数组,返回 null;
  • 没有使用 @Param 注解,且数组里只有一个对象,返回该对象;
  • 否则返回 Map<String, Object>

第三种情况下,Map<String, Object> 的数据首先根据 paramsargs 里取。params 是一个 Map<Integer, String>,存储了形参的顺序和名字,名字的规则是:

  • @Param 注解,使用注解的 value
  • 否则,使用形参顺序

例如:

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

对应的 params(使用 json 格式以便观察):

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

注意到只要不带 @Param 注解,就需要使用下标了。

这还没有结束,为了方便允许使用下标,MyBatis 还按 params 顺序设置了另一组值,使得输出的结果类似于:

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

当然了,如果你手动指定的参数名恰好为 param<Index> 以至于跟这条规则重复了,那么 MyBatis 会跳过已经存在的键。

不管是 selectOne 还是 selectMap 方法,都是通过 selectList 执行查询的,不管是 insert 还是 delete 方法,都是通过 update 方法执行的。

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>

转载于:https://my.oschina.net/tridays/blog/769732

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值