MyabtisPlus(4):参数值设置

311 阅读1分钟

参数对象的构建与获取

// MybatisMapperProxy的cachedMapperMethod方法中,如果methodCache没有methodName的话,会new
/* 最终会走到这个构造函数
该构造函数有一个Map类型的变量names,它的key是方法参数的下标,如果参数有@Param注释,value是@Param注解值,否则,是参数的名字
例如(@Param("id") int id1,int id2),那么names的值为0->id,1->id2
*/
ParamNameResolver->ParamNameResolver():
    // 方法的参数类型
    final Class<?>[] paramTypes = method.getParameterTypes();
    // 方法参数的注解信息
    final Annotation[][] paramAnnotations = method.getParameterAnnotations();
    final SortedMap<Integer, String> map = new TreeMap<>();
    int paramCount = paramAnnotations.length;
    for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) {
        String name = null;
        for (Annotation annotation : paramAnnotations[paramIndex]) {
            // 遍历参数注解,如果有@Param注解的话,name是注解值
            if (annotation instanceof Param) {
                // hasParamAnnotation,只要有一个参数带@Param,就为true
                hasParamAnnotation = true;
                name = ((Param) annotation).value();
                break;
            }
        }
        // 没有@Param注解,就取参数名称
        if (name == null) {
            name = getActualParamName(method, paramIndex);
        }
        map.put(paramIndex, name);
    }
    names = Collections.unmodifiableSortedMap(map);

ParamNameResolver->getNamedParams():
    final int paramCount = names.size();
    if (args == null || paramCount == 0) {
        return null;
    // 如果只有一个参数并且不带@Param标签的话,返回该参数
    } else if (!hasParamAnnotation && paramCount == 1) {
        return args[names.firstKey()];
    } else {
        // 否则返回Map类型,它的key是names里的value,值是对应参数值  
        ......
    }
    

总结

  1. 如果只有一个参数,并且不带@Param注解的话,返回的是调用该方法时所传对象值,否则返回的都是map类型

  2. 后面的取值中,如果返回的是参数对象值

    • 如果是非预编译符$类型(Integer x→${name}或Tree tree→${tree.id}),会利用MetaObject.getValue()最终调用Integer.getName()或Tree.getTree()方法
    • 如果是预编译符#类型(Integer x→#{name}),走的是最终拼接SQL探究里的MybatisDefaultParameterHandler->setParameters()同段逻辑
  3. 如果返回的是map类型,不论是否预编译,调用map.get("name")方法获取参数值

参数情况names参数值sql语句获取过程
(Tree tree)0->treetree对象${id}Tree.getId()
(Tree tree)0->treetree对象#{id}Tree.getId()
(Integer id)0->idid值${id}Integer.getId()
(Integer id)0->idid值#{id}id值
(@Param("tree") Tree tree)0->treetree->tree对象#/$ {tree.id}map.get("tree")、tree.getId()
(@Param("origin") Integer id)0->originorigin->id值#/$ {origin}map.get("origin")
(Integer id1,Integer id2)0->id1,1->id2id1->id1值,id2->id2值#/$ {id1}map.get("id1")
(@Param("origin")Integer id1,@Param("now")Integer id2)0->origin,1->noworigin->id1值,now->id2值#/$ {now}map.get("now")