MyBatis @Param注解的实现

先说结论:

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

  • Map中会有param1, param2这样的key,其顺序对应输入参数的顺序。无论是否有@Param注解。
  • 对于@Param注解的参数,Map中会保存注解中给定的名字作为key
  • 对于没有用@Param注解的参数,Map中会用1、2、3 ..这样的数字作为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注解内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Mybatis使用@param注解四种情况解析

    一.方法有多个参数 例如: 接口方法: @Mapper public interface UserMapper { Integer insert(@Param("username") String username, @Param("address") String address); } 对应的xml: <insert id="insert" parameterType="org.javaboy.helloboot.bean.U

  • 解决Mybatis的@Param()注解导致分页失效的问题

    @Param注解导致分页失效-分页拦截器 问题描述 在使用mybatis分页时,使用@Param注解传入了两个对象,分页失效,查询出的总是全部的数据. 出现问题时,分页策略为:分页拦截器实现的分页 [错误写法] service写法: public Page<Entity> getByNidAndEntity(Page<Entity> page,String nid,Entity entity){ entity.setPage(page); page.setList(dao.getB

  • mybatis省略@Param注解操作

    项目是Springboot+mybatis,每次写一堆@Param注解感觉挺麻烦,就找方法想把这个注解给省了,最后确实找到一个方法 1.在mybatis的配置里有个属性useActualParamName,允许使用方法签名中的名称作为语句参数名称 我用的mybatis:3.4.2版本Configuration中useActualParamName的默认值为true 源码简单分析: MapperMethod的execute方法中获取参数的方法convertArgsToSqlCommandParam

  • Mybatis中@Param注解的作用说明

    目录 @Param注解的作用说明 1.关于@Param 2.原始的方法 3.使用@Param @Param注解和参数使用 1.使用@Param注解 2.不使用@Param注解 @Param注解的作用说明 1.关于@Param @Param是MyBatis所提供的(org.apache.ibatis.annotations.Param),作为Dao层的注解,作用是用于传递参数,从而可以与SQL中的的字段名相对应,一般在2=<参数数<=5时使用最佳. 2.原始的方法 当只有一个参数时,没什么好说的

  • mybatis多个接口参数的注解使用方式(@Param)

    1 简介 1.1 单参数 在 Mybatis 中, 很多时候, 我们传入接口的参数只有一个. 对应接口参数的类型有两种, 一种是基本的参数类型, 一种是 JavaBean . 例如在根据主键获取对象时, 我们只需要传入一个主键的参数即可. 而在插入, 更新等操作时, 一般会涉及到很多参数, 我们就使用 JavaBean . 1.2 多参数 但是, 在实际的情况中, 我们遇到类似这样的情况可能: 接口需要使用的参数多于一个: 接口需要使用的参数又远少于对应 JavaBean 的成员变量, 或者需要

  • 解决MyBatis @param注解参数类型错误异常的问题

    问题现象 今天使用mybatis遇到个很奇怪的问题,我使用一个参数@param("threshold"),类型是java的double,但是很奇怪,一直告诉我参数转换错误,int不能转double,我就奇怪了,哪里来的int. 解决办法 我感觉可能使用用到了mybatis的关键字,所以就把threshold换了个名字,果然好了. 问题原因 某些关键词,mybatis会认为是某种类型,下面列出来一些,后面发现再补充. size, threshold, modCount是int类型 loa

  • Mybatis Mapper中多参数方法不使用@param注解报错的解决

    目录 问题描述 寻求解决方案 寻找原因 拓展延伸 在使用低版本的Mybatis的时候,Mapper中的方法如果有多个参数时需要使用@param注解,才能在对应xml的sql语句中使用参数名称获取传入方法的参数值,否则就会报错.本文结合自身在真实开发环境中使用IDEA开发时遇到的问题来共同探讨一下不使用@Param注解报错背后的原因以及解决方案. 问题描述 最近使用IDEA进行开发,项目使用SpringBoot+Mybatis3.4.6,同样的代码检出到本地IDEA后运行,在一个业务查询模块报错,

  • MyBatis @Param注解的实现

    先说结论: 当输入参数只有一个且没有使用@Param注解时,MyBatis会直接传递这个参数:当输入参数多于一个,或者使用了@Param注解时,MyBatis会将参数封装在Map中传递,这时的Map的key分为以下几种可能: Map中会有param1, param2这样的key,其顺序对应输入参数的顺序.无论是否有@Param注解. 对于@Param注解的参数,Map中会保存注解中给定的名字作为key 对于没有用@Param注解的参数,Map中会用1.2.3 ..这样的数字作为key,按顺序保存

  • Mybatis省略@Param注解原理分析

    目录 1.新建mybatis的Demo项目 2.添加-parameters参数后的执行结果如下 3.springboot项目为什么不用另外配置-parameters参数呢 环境配置: jdk1.8 mybatis3.4.1 springboot2.0 起始原因: 编写mybatis的Demo程序时,mapper传递多参数时,需要添加@param注解指定传递参数名称,而在springboot整合的mybatis则可以省略@param注解.于是乎,开始探究原因. 涉及到的知识点: jdk8新增了-p

  • mybatis中@Param注解总是报取不到参数问题及解决

    目录 @Param注解总是报取不到参数 错误如下 @Param注解详细使用方法 1.@Param这个注解是用来解决接口方法有多个参数时 2.可以修饰JavaBean对象.Map集合等 3.@Param参数其实可加可不加 4.使用@Param注解好处 @Param注解总是报取不到参数 springboot+mybatis项目中,在mapper 层传多个参数,请求时总是报参数取不到,快疯了,我发誓xml层没问题,mapper层参数名也没问题 错误如下 百度了好久,一直让我检查.xml文件是否存在问题

  • Mybatis中@Param注解的用法详解

    目录 1.概述 2.实例: 实例一:@Param注解基本类型的参数 实例二:@Param注解JavaBean对象 3.注意点 附:为什么要用@param 总结 1.概述 首先明确这个注解是为SQL语句中参数赋值而服务的. @Param的作用就是给参数命名,比如在mapper里面某方法A(int id),当添加注解后A(@Param("userId") int id),也就是说外部想要取出传入的id值,只需要取它的参数名userId就可以了.将参数值传如SQL语句中,通过#{userId

随机推荐