文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

MyBatis@Param注解的实现

2024-04-02 19:55

关注

先说结论:

当输入参数只有一个且没有使用@Param注解时,MyBatis会直接传递这个参数;当输入参数多于一个,或者使用了@Param注解时,MyBatis会将参数封装在Map中传递,这时的Map的key分为以下几种可能:

下面来看一下源码。

首先,判断一个方法中是否有用@Param注解的参数:

    private boolean hasNamedParams(Method method) {
      final Object[][] paramAnnos = method.getParameterAnnotations();
      for (Object[] paramAnno : paramAnnos) {
        for (Object aParamAnno : paramAnno) {
          if (aParamAnno instanceof Param) {
            return true;
          }
        }
      }
      return false;
    }

如果有用@Param注解的参数,取出注解中给出的参数名:

    private String getParamNameFromAnnotation(Method method, int i, String paramName) {
      final Object[] paramAnnos = method.getParameterAnnotations()[i];    // 获取第i个参数的注解
      for (Object paramAnno : paramAnnos) {
        if (paramAnno instanceof Param) {
          paramName = ((Param) paramAnno).value();
          break;
        }
      }
      return paramName;
    }

注意方法的输入参数,method表示是哪个方法上,i 表示第几个参数,  paramName是传进来的参数名,如果该参数没有用@Param注解,则返回传进来的paramName。

下面这个方法返回一个TreeMap(有序),其key表示参数的顺序,比如key=0代表第0个参数;value表示参数的名字,如果有用@Param注解标注,则为标注的参数名,否则和key相等,即用参数的序号作为参数的名字。

    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) {    //如果有使用@Param注解,则获取注解标注的参数名
            paramName = getParamNameFromAnnotation(method, i, paramName);    // 这里paramName作为参数传进来,表示默认值
          }
          params.put(i, paramName);
        }
      }
      return params;
    }

其中hasNamedParameters只是从整个方法的维度,给出该方法是否有使用@Param注解的参数;即使其值为true,具体到某一个参数上面,可能没有使用@Param注解,因此调用getParamNameFromAnnotation传入的paramName就作为默认值返回,即参数的序号。

最后将调用方法的参数转换为MyBatis内部使用的参数:

 public Object convertArgsToSqlCommandParam(Object[] args) {
      final int paramCount = params.size();
      if (args == null || paramCount == 0) {
        return null;
      } else if (!hasNamedParameters && paramCount == 1) {
        return args[params.keySet().iterator().next().intValue()];
      } else {
        final Map<String, Object> param = new ParamMap<Object>();
        int i = 0;
        for (Map.Entry<Integer, String> entry : params.entrySet()) {
          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);
          if (!param.containsKey(genericParamName)) {
            param.put(genericParamName, args[entry.getKey()]);
          }
          i++;
        }
        return param;
      }
    }

其中args为Dao方法的输入参数,这里已经转换成了数组,其实就是动态代理的invoke方法传入的参数。

该方法首先对输入参数进行计数,使用的params就是前面介绍的getParams方法的返回值。

if (!hasNamedParameters && paramCount == 1)

上面的条件判断,即方法没有使用@Param注解,且只有一个参数,这时返回

args[params.keySet().iterator().next().intValue()]

即直接将其作为Object返回。

如果上面的条件不满足的话,首先新建一个Map作为返回值:

final Map<String, Object> param = new ParamMap<Object>();

然后,设置map的key和value:

param.put(entry.getValue(), args[entry.getKey().intValue()]);

然后为了兼容性,做了如下操作

final String genericParamName = "param" + String.valueOf(i + 1);
if (!param.containsKey(genericParamName)) {
    param.put(genericParamName, args[entry.getKey()]);
}

即设置param1、param2这样的key。

到此为止,需要的参数对象Object就构建完成,其中封装了Dao传入的多个参数,并根据参数是否有@Param注解,影响了参数对象的类型(是否是map)。

参数封装完成之后,下一步将其传递给SqlSession。

到此这篇关于MyBatis @Param注解的实现的文章就介绍到这了,更多相关MyBatis @Param注解内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯