乐趣区

关于mybatis:聊聊mybatis的ParamNameResolver

在 mybatis 的 interceptor 获取 MapperMethod.ParamMap 这种参数类型时,常常会多出 param1,param2,collection,list,array 这些参数,这些不是接口本人定义的,而是 ParamNameResolver 主动增加的

ParamNameResolver

org/apache/ibatis/reflection/ParamNameResolver.java

public class ParamNameResolver {

  public static final String GENERIC_NAME_PREFIX = "param";

  /**
   * <p>
   * A single non-special parameter is returned without a name.
   * Multiple parameters are named using the naming rule.
   * In addition to the default names, this method also adds the generic names (param1, param2,
   * ...).
   * </p>
   *
   * @param args
   *          the args
   * @return the named params
   */
  public Object getNamedParams(Object[] args) {final int paramCount = names.size();
    if (args == null || paramCount == 0) {return null;} else if (!hasParamAnnotation && paramCount == 1) {Object value = args[names.firstKey()];
      return wrapToMapIfCollection(value, useActualParamName ? names.get(0) : null);
    } else {final Map<String, Object> param = new ParamMap<>();
      int i = 0;
      for (Map.Entry<Integer, String> entry : names.entrySet()) {param.put(entry.getValue(), args[entry.getKey()]);
        // add generic param names (param1, param2, ...)
        final String genericParamName = GENERIC_NAME_PREFIX + (i + 1);
        // ensure not to overwrite parameter named with @Param
        if (!names.containsValue(genericParamName)) {param.put(genericParamName, args[entry.getKey()]);
        }
        i++;
      }
      return param;
    }
  }

  //......

}

getNamedParams 办法针对单个参数没有加 @Param 的场景会调用 wrapToMapIfCollection,其余的则应用 param1,param2 这种,这里用了 contains,也就是如果自身命名就有蕴含 param1,param2 这种则不会增加

wrapToMapIfCollection

org/apache/ibatis/reflection/ParamNameResolver.java

  /**
   * Wrap to a {@link ParamMap} if object is {@link Collection} or array.
   *
   * @param object a parameter object
   * @param actualParamName an actual parameter name
   *                        (If specify a name, set an object to {@link ParamMap} with specified name)
   * @return a {@link ParamMap}
   * @since 3.5.5
   */
  public static Object wrapToMapIfCollection(Object object, String actualParamName) {if (object instanceof Collection) {ParamMap<Object> map = new ParamMap<>();
      map.put("collection", object);
      if (object instanceof List) {map.put("list", object);
      }
      Optional.ofNullable(actualParamName).ifPresent(name -> map.put(name, object));
      return map;
    } else if (object != null && object.getClass().isArray()) {ParamMap<Object> map = new ParamMap<>();
      map.put("array", object);
      Optional.ofNullable(actualParamName).ifPresent(name -> map.put(name, object));
      return map;
    }
    return object;
  }

wrapToMapIfCollection 对于 collection 类型增加 collection,对于 list 类型还会增加 list 参数,如果是 array 类型则会增加 array 参数,不过这里应用了 ifPresent,也就是如果自身参数名蕴含了则不会增加

小结

mybatis 的 ParamNameResolver 针对单个参数没有加 @Param 的场景会调用 wrapToMapIfCollection,最多会增加 collection、list、array 这些参数;其余的则多增加 param1,param2 这类参数。

退出移动版