mybatis参数的处理

在使用mybatis时,最常使用的就是接口形式,尤其是和springmvc整合后。这种方式使用比较简单。
通过上篇mybatis通过接口查找对应的mapper.xml以及方法执行
可以了解到接口到mapper.xml的过程。
那么在mapper.xml中如何与接口中的参数对应起来呢?
比如:

public interface RedPacketDao {
	List<edpacketPO> getRedpacktList(@Param("id")Long id,@Param("statusList")List<Integer> statusList);
	
}
<select id="getRedpacktList" resultType="Redpacket">
		SELECT id, price, status, receive_time 
		from redpacket
		where redpacket_id = #{id} 
		and status in
		<foreach collection="statusList" item="status" open="(" separator="," close=")">
			#{status}
		</foreach>
	</select>

对于参数id和statusList,mapper.xml是如何识别的?

之前我们了解到在方法的执行时调用MapperProxy.java中的invoke()方法。
这个方法会调用MapperMethod.java中MapperMethod.execute(sqlSession, args);
在这个方法中会解析参数:

 Object param = method.convertArgsToSqlCommandParam(args);
public Object convertArgsToSqlCommandParam(Object[] args) {
      final int paramCount = params.size();
      //参数为空或者参数个数为0
      if (args == null || paramCount == 0) {
        return null;
        //如果没有使用@param注解并且只有一个参数
      } else if (!hasNamedParameters && paramCount == 1) {
        return args[params.keySet().iterator().next().intValue()];
      } else {
        final Map<String, Object> param = new ParamMap<Object>();
        int i = 0;
        //参数为多个时,对params进行遍历
        for (Map.Entry<Integer, String> entry : params.entrySet()) {
        //如果使用注解,entry.getValue()则是注解的值,否则则是顺序的序号
          param.put(entry.getValue(), args[entry.getKey().intValue()]);
          // issue #71, add param names as param1, param2...but ensure backward compatibility
          final String genericParamName = "param" + String.valueOf(i + 1);
          //存储参数key为param1,param2的形式
          if (!param.containsKey(genericParamName)) {
            param.put(genericParamName, args[entry.getKey()]);
          }
          i++;
        }
        return param;
      }
    }

这里面有个params,params的获取如下:

 private SortedMap<Integer, String> getParams(Method method, boolean hasNamedParameters) {
      final SortedMap<Integer, String> params = new TreeMap<Integer, String>();
      final Class<?>[] argTypes = method.getParameterTypes();
      //按照参数顺序遍历
      for (int i = 0; i < argTypes.length; i++) {
        if (!RowBounds.class.isAssignableFrom(argTypes[i]) && !ResultHandler.class.isAssignableFrom(argTypes[i])) {
        //先赋值为参数的顺序号
          String paramName = String.valueOf(params.size());
          if (hasNamedParameters) {
          //如果使用注解则赋值为注解值
            paramName = getParamNameFromAnnotation(method, i, paramName);
          }
          //放入params中
          params.put(i, paramName);
        }
      }
      return params;
    }
private String getParamNameFromAnnotation(Method method, int i, String paramName) {
      final Object[] paramAnnos = method.getParameterAnnotations()[i];
      for (Object paramAnno : paramAnnos) {
        if (paramAnno instanceof Param) {
        //获取注解名称
          paramName = ((Param) paramAnno).value();
          break;
        }
      }
      return paramName;
    }

所以params是Map<Integer, String>类型,根据接口方法中参数的顺序记录参数的定义名字,如果使用@param注解,就会把注解的值作为params的value,否则使用序号作为params的value。
例子如下:

void update(String name,Long id,@Param("password") String password);

生成的params如下:

{
    0:'0',
    1:'1',
    2:"password"
}

对于参数的解析请参见上面代码上的注释。
鉴于我们可能会在sql语句中使用动态sql,所以有多个参数时做好使用@params注解,否则可能会出现值的混乱。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值