mybatis参数处理

总结
  • 多个参数:mybatis会做特殊处理。多个参数会被封装成一个map
    key : param1….paramN,或者使用@Param注解指定的值
    value:传入的参数值
//id获取的方式有两种  #{param1} 或者#{id}
//name获取的方式有两种  #{param2}或者 #{name}
selectUserByIdAndName(@Param("id") Integer id, @Param("name") String name);
传参的方式
  • POJO:如果多个参数正好是业务逻辑的数据模型,就可以直接传入pojo;使用#{属性名}:取出传入的pojo属性值
  • Map :如果多个参数不是业务模型中的数据,没有对应的pojo,不经常使用,为了方便,也可以传入map;#{key}:取出map中对应的值
  • TO : 如果多个参数不是业务模型中的数据,但经常要使用,推荐编写一个TO(Transfer object)

//取值:id==>#{id/param1}  username==>#{param2}
User selectUserByIdAndName(@Param("id") Integer id, String name);
//取值:id==>#{param1}  username==>#{param2.username}
User selectUserByIdAndName(Integer id, User user);
/**
注意 如果是collection(List、Set)类型或者数组,mybatis也会做特殊处理,也是把传入的list或者数组封装在map中。key根据参数的不同,分别为collection、list、array
*/
//取值:取出第一个id的值  #{list[0]}
User selectUserByIds(List<Integer> ids);

源码分析
//names:在构造器的时候就确定好了
//selectUserByIdAndName(@Param("id") Integer id, @Param("name") String name);  返回("0","id"),("1","name")
public ParamNameResolver(Configuration config, Method method) {
    final Class<?>[] paramTypes = method.getParameterTypes();
    final Annotation[][] paramAnnotations = method.getParameterAnnotations();
    final SortedMap<Integer, String> map = new TreeMap<Integer, String>();
    int paramCount = paramAnnotations.length;
    // get names from @Param annotations
    for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) {
      if (isSpecialParameter(paramTypes[paramIndex])) {
        // skip special parameters
        continue;
      }
      String name = null;
      for (Annotation annotation : paramAnnotations[paramIndex]) {
        if (annotation instanceof Param) {
          hasParamAnnotation = true;
		//获取标注了param注解的参数@Param的值,以上述方法为例,则取到值的值为id,name
          name = ((Param) annotation).value();
          break;
        }
      }
      if (name == null) {
        // @Param was not specified.
        if (config.isUseActualParamName()) {
		//使用了全局配置,useActualParamName(jdk1.8):name=参数名
          name = getActualParamName(method, paramIndex);
        }
        if (name == null) {
          // use the parameter index as the name ("0", "1", ...)
          // gcode issue #71
  		//没有param注解,没有全局配置,name=当前元素的索引
          name = String.valueOf(map.size());
        }
      }
      map.put(paramIndex, name);
    }
    names = Collections.unmodifiableSortedMap(map);
  }
//使用ParamNameResolver解析参数封装为map
public Object getNamedParams(Object[] args) {
        int paramCount = this.names.size();
        if (args != null && paramCount != 0) {
		//如果没有param注解并且参数只有一个,则直接返回单个参数
            if (!this.hasParamAnnotation && paramCount == 1) {
                return args[(Integer)this.names.firstKey()];
            } else {
                Map<String, Object> param = new ParamMap();
                int i = 0;

				//遍历names集合
                for(Iterator var5 = this.names.entrySet().iterator(); var5.hasNext(); ++i) {
                    Entry<Integer, String> entry = (Entry)var5.next();
					//value的值可以是param的属性或者参数索引
					//param中放入{"id":arg[0],"name":arg[1]}
                    param.put(entry.getValue(), args[(Integer)entry.getKey()]);
                    String genericParamName = "param" + String.valueOf(i + 1);
                    if (!this.names.containsValue(genericParamName)) {
					/*同时param中放入{"param1":arg[0],"param2":arg[1]},最终的效果就是如果有param注解,使用#{指定的key}或者#{paramN}获取参数,没有注解,使用#{paramN}获取参数*/
                        param.put(genericParamName, args[(Integer)entry.getKey()]);
                    }
                }

                return param;
            }
        } else {
            return null;
        }
    }

经过参数封装后,可以获取到一个map,但是mybatis对参数又进行了一次处理

//如果是Collection,则map的key=collection,如果是List,则key=list,如果是数组,则key=array
private Object wrapCollection(final Object object) {
    if (object instanceof Collection) {
      StrictMap<Object> map = new StrictMap<>();
      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<>();
      map.put("array", object);
      return map;
    }
    return object;
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值