MyBatisSQL参数占位符与全局属性useActualParamName详细介绍与原理剖析

这个世界并不缺Java工程师,缺的是有“内涵”的工程师

从本质看,Mybatis其实是 SQL 语句与数据做映射作用的框架,是一个映射器。在查询数据的时候,SQL 语句的参数占位符起着至关重要的作用。

与参数占位符映射的配置中有一个全局变量useActualParamName。

关于useActualParamName参数的解释:允许使用方法签名中的名称作为语句参数名称。

mybatis.configuration.use-actual-param-name=true(默认是true

在研究参数占位符书写规则的时候,有几个代码块至关重要。

package org.apache.ibatis.reflection
//ParamNameResolver类的构造函数,主要作用是初始化参数
//得到一个Map<Integer, String>(key=参数索引,value=参数名称),方便后面参数映射
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;
    // 遍历每一个参数
    for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) {
    	//如果为特殊参数(RowBounds(分页对象) 和 ResultHandler(结果处理)),则不会记入mapper的实际参数
      if (isSpecialParameter(paramTypes[paramIndex])) {
        // skip special parameters
        continue;
      }
      String name = null;
      //判断参数是否由@Param注解修饰
      for (Annotation annotation : paramAnnotations[paramIndex]) {
        if (annotation instanceof Param) {
          hasParamAnnotation = true;
          name = ((Param) annotation).value();
          break;
        }
      }
      if (name == null) {
        // @Param was not specified.
        if (config.isUseActualParamName()) {
        //如果配置了useActualParamName=true的话,则取实际参数的名称
          name = getActualParamName(method, paramIndex);
        }
        if (name == null) {
          //否则,该参数的名称为0,1....n
          name = String.valueOf(map.size());
        }
      }
      map.put(paramIndex, name);
    }
    names = Collections.unmodifiableSortedMap(map);
  }
//此接口的作用:获取参数对象集合:
//map<String,Object>(key=参数名,value=参数值) |  实际的对象(只有一个参数 & 没有参数注解)
public Object getNamedParams(Object[] args) {
    final int paramCount = names.size();
    if (args == null || paramCount == 0) {
      return null;
    } else if (!hasParamAnnotation && paramCount == 1) {
    	//只有一个参数 & 没有参数注解,直接返回值
      return args[names.firstKey()];
    } else {
      final Map<String, Object> param = new ParamMap<Object>();
      int i = 0;
      for (Map.Entry<Integer, String> entry : names.entrySet()) {
      	//保存key为参数名,value为参数值的集合数据
        param.put(entry.getValue(), args[entry.getKey()]);
        // add generic param names (param1, param2, ...)
        final String genericParamName = GENERIC_NAME_PREFIX + String.valueOf(i + 1);
        // ensure not to overwrite parameter named with @Param
        if (!names.containsValue(genericParamName)) {
        	//保存key为param0-paramn规则的字符串,value为参数值的集合对象
          param.put(genericParamName, args[entry.getKey()]);
        }
        i++;
      }
      return param;
    }
  }

测试

mybatis.configuration.use-actual-param-name=false
public interface DemoMapper {
    @Select("select username from user where id=#{id}")
    //不加@Param参数
    //mybatis.configuration.use-actual-param-name=false
     String getUserById(int id);
}

进入单参数处理程序,查询成功!
在这里插入图片描述

public interface DemoMapper {
    @Select("select username from user where id=#{id}")
    @Select("select username from user where id=#{param1}")
    //加上@Param参数
    //mybatis.configuration.use-actual-param-name=false
     String getUserById(@Param("id") int id);
}

进入多参数处理程序,key为占位符,value为参数值,使用对应占位符(key)都可以查询成功!
在这里插入图片描述

public interface DemoMapper {
    @Select("select username from user where id=#{0} and sex=#{param2}")
    @Select("select username from user where id=#{0} and sex=#{1}")
    //不加@Param参数
    //mybatis.configuration.use-actual-param-name=false
     String getUserById(int id,int sex);
}

进入多参数处理程序,key为占位符,value为参数值,使用对应占位符(key)都可以查询成功!
在这里插入图片描述

public interface DemoMapper {
    @Select("select username from user where id=#{id} and sex=#{sex}")
    @Select("select username from user where id=#{param1} and sex=#{sex}")
    //加上@Param参数
    //mybatis.configuration.use-actual-param-name=false
     String getUserById(@Param("id") int id,@Param("sex") int sex);
}

进入多参数处理程序,key为占位符,value为参数值,使用对应占位符(key)都可以查询成功!
在这里插入图片描述

mybatis.configuration.use-actual-param-name=true
public interface DemoMapper {
    @Select("select username from user where id=#{id}")
    //不加@Param参数
    //mybatis.configuration.use-actual-param-name=true
     String getUserById(int id);
}

进入单参数处理程序,查询成功!
在这里插入图片描述

public interface DemoMapper {
    @Select("select username from user where id=#{id}")
    @Select("select username from user where id=#{param1}")
    //加上@Param参数
    //mybatis.configuration.use-actual-param-name=true
     String getUserById(@Param("id") int id);
}

进入多参数处理程序,key为占位符,value为参数值,使用对应占位符(key)都可以查询成功!
在这里插入图片描述

```java
public interface DemoMapper {
    @Select("select username from user where id=#{id} and sex=#{sex}")
    @Select("select username from user where id=#{param1} and sex=#{sex}")
    //不加@Param参数
    //mybatis.configuration.use-actual-param-name=true
     String getUserById(int id,int sex);
}

进入多参数处理程序,key为占位符,value为参数值,使用对应占位符(key)都可以查询成功!
在这里插入图片描述

public interface DemoMapper {
    @Select("select username from user where id=#{id} and sex=#{sex}")
    @Select("select username from user where id=#{param1} and sex=#{sex}")
    //加上@Param参数
    //mybatis.configuration.use-actual-param-name=true
     String getUserById(int id,int sex);
}

进入多参数处理程序,key为占位符,value为参数值,使用对应占位符(key)都可以查询成功!
在这里插入图片描述

总结:

单参数:

不加注解@Param:参数use-actual-param-name不影响占位符,填什么都可以
加注解@Param:参数use-actual-param-name不影响占位符,但是只能填参数名或者param1-n格式的占位符

多参数:
只有参数use-actual-param-name为false,且不加注解@param这种情况占位符需要填0-n或者param1-n格式的占位符
其他情况填参数名或者param1-n格式的占位符

bilibili账号:段某人
文章持续更新,可以微信扫码关注第一时间阅读
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值