转载自  mybatis多个参数(不使用@param注解情况下),sql参数占位符正确写法

useActualParamName配置

useActualParamName 允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的工程必须采用Java 8编译,并且加上-parameters选项。(从3.4.1开始) true | false true

mybatis的全局配置useActualParamName决定了mapper中参数的写法,默认为true

代码展示:

@Test
public void findUserById() {SqlSession sqlSession = getSessionFactory().openSession();UserDao userMapper = sqlSession.getMapper(UserDao.class);User user = userMapper.findUserById(1,"lpf");Assert.assertNotNull("没找到数据", user);
}
public interface UserDao {User findUserById (int id,String name);
}

1.如果useActualParamName设置为true时

传递参数需要使用

#{arg0}-#{argn}或者#{param1}-#{paramn}

比如:

<select id="findUserById" resultType="com.lpf.entity.User" >select * from m_user where id = #{arg0}  and name =#{arg1}
</select>

或者

<select id="findUserById" resultType="com.lpf.entity.User" >select * from m_user where id = #{param1}  and name =#{param2}
</select>

2.如果useActualParamName设置为false时

传递参数需要使用

#{0}-#{n}或者#{param1}-#{paramn}

<select id="findUserById" resultType="com.lpf.entity.User" >select * from m_user where id = #{0}  and name =#{1}
</select>

或者

<select id="findUserById" resultType="com.lpf.entity.User" >select * from m_user where id = #{param1}  and name =#{param2}
</select>

下面是多个参数的错误写法直接写参数名(如果方法只有一个参数是可以用参数名代替的,其实如果只有一个参数,任何名称都是可以的)

<select id="findUserById" resultType="com.lpf.entity.User" >select * from m_user where id = #{id}  and name =#{name}
</select>

源码解读(3.4.6):

在mapper的代理对象调用方法时,最终会是MapperMethod对象的execute方法。如下:

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {try {// 如果目标方法是Object类继承来的,直接调用目标方法if (Object.class.equals(method.getDeclaringClass())) {return method.invoke(this, args);} else if (isDefaultMethod(method)) {return invokeDefaultMethod(proxy, method, args);}} catch (Throwable t) {throw ExceptionUtil.unwrapThrowable(t);}// 从缓存中获取MapperMethod 对象,如果没有就创建新的并添加final MapperMethod mapperMethod = cachedMapperMethod(method);// 执行sql 语句return mapperMethod.execute(sqlSession, args);
}

MapperMethod的一个内部类MethodSignature封装了Mapper接口中定义的方法的相关信息。而MethodSignature的一个属性ParamNameResolver对象处理接口中定义的方法的参数列表。

ParamNameResolver 的属性

// 记录参数在参数列表中的位置索引与参数名称之间的对应关系
private final SortedMap<Integer, String> names;// 记录对应的方法参数是否使用了@Param注解
private boolean hasParamAnnotation;

ParamNameResolver的构造函数

/*** 通过反射读取方法中的信息,并初始化上面两个字段* @param config* @param method*/
public ParamNameResolver(Configuration config, Method method) {// 获取参数列表中每个参数的类型final Class<?>[] paramTypes = method.getParameterTypes();// 获取参数列表上的注解  @Paramfinal Annotation[][] paramAnnotations = method.getParameterAnnotations();// 该集合用于记录参数索引与参数名称的对应关系final SortedMap<Integer, String> map = new TreeMap<Integer, String>();int paramCount = paramAnnotations.length;// 遍历所有参数for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) {if (isSpecialParameter(paramTypes[paramIndex])) {// 如果参数是RowBounds类型或者ResultHandler类型,则跳过该参数continue;}String name = null;// 遍历该参数上的注解集合for (Annotation annotation : paramAnnotations[paramIndex]) {if (annotation instanceof Param) {// 获取@Param注解指定的参数名称hasParamAnnotation = true;name = ((Param) annotation).value();break;}}// 没有@Param注解的话 执行下面逻辑if (name == null) {// useActualParamName==true时  即name = arg0 ...if (config.isUseActualParamName()) {name = getActualParamName(method, paramIndex);}if (name == null) {//useActualParamName == false是  即 name="0" ...// use the parameter index as the name ("0", "1", ...)// 使用参数的索引作为其名称name = String.valueOf(map.size());}}map.put(paramIndex, name);}names = Collections.unmodifiableSortedMap(map);
}

names集合主要是在ParamNameResolver.getNamedParams方法中使用

/**** @param args 用户传入的参数值列表* @return*/
public Object getNamedParams(Object[] args) {final int paramCount = names.size();if (args == null || paramCount == 0) {return null;} else if (!hasParamAnnotation && paramCount == 1) {// 未使用@Param注解且参数列表只有一个return args[names.firstKey()];//即args[0] 参数的值} else {// 下面是为参数创建param+索引的格式作为默认参数名称 如:param1  下标从1开始final Map<String, Object> param = new ParamMap<Object>();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 + String.valueOf(i + 1);// ensure not to overwrite parameter named with @Paramif (!names.containsValue(genericParamName)) {param.put(genericParamName, args[entry.getKey()]);}i++;}return param;}
}

总结:

1.如果接口方法有一个或多个参数,并且使用了@Param注解,sql语句中的参数用注解的value值,

2.如果接口方法的参数只有一个,并且没有使用@Parma注解sql语句直接使用任何名称均可。

3.如果接口的方法有多个参数,并且没有使用@Parma注解,sql语句使用param1...paramn是不会错的。

4.sql语句中的参数占位符名称和接口方法的参数名称没有什么关系。

mybatis多个参数(不使用@param注解情况下),sql参数占位符正确写法相关推荐

  1. get占位符传多个参数_mybatis多个参数(不使用@param注解情况下),sql参数占位符正确写法...

    useActualParamName配置 useActualParamName 允许使用方法签名中的名称作为语句参数名称. 为了使用该特性,你的工程必须采用Java 8编译,并且加上-paramete ...

  2. C++之再探参数绑定bind、bind1st、bind2nd、placeholders占位符

    相关博文:C++头文件<functional>和bind.placeholders占位符使用简单例子 相关博文:<Essential C++>笔记之设计一个泛型算法(二) 相关 ...

  3. There is no getter for property named ‘col‘ in ‘class String‘,不是说一个参数不需要@Param注解吗?#{}和${}的区别

    1. 当一个String类型的参数作为sql语句的where条件可以正常运行 2. 当一个String类型的参数不作为sql语句的where条件,而表示一个表名或列名,报错:Cause: com.my ...

  4. java 方法参数绑定_java在注解中绑定方法参数的解决方案

    我们有这样子的需求,需要记录用户操作某个方法的信息并记录到日志里面,例如,用户在保存和更新任务的时候,我们需要记录下用户的ip,具体是保存还是更新,调用的是哪个方法,保存和更新的任务名称以及操作是否成 ...

  5. iview on-row-dblclick参数存在多个的情况下传递自定义参数

    @on-row-dblclick="editRow(arguments,index)" 当前行的数据 index 2.如果参数是一个 test($event,自定义参数)

  6. parameterType和@Param注解用法

    在mybatis映射接口的配置中,有select,insert,update,delete等元素都提到了 parameterType的用法,parameterType为输入参数,在配置的时候,配置相应 ...

  7. mybatis 不生效 参数_MyBatis参数使用@Param注解获取不到自增id问题

    一.背景 群里有个哥们分享了一个mybatis的小"坑". "分享一个菜鸡点:mybatis中使用@param注解后,要keyProperty="注解名.id& ...

  8. Mybatis中的@Param注解

    前言 今天在使用Mybatis时遇到一个问题,主要出错原因在于Mybatis的@Param注解,如果我不在参数前面加上@Param注解,数据库操作就会报错,如下: @Param作用 @Param注解的 ...

  9. 关于Mybatis的@Param注解

    Mybatis 作为一个轻量级的数据持久化框架,目前(2018)的应用非常广泛,基本可以取代Hibernate.关于 @param 这个注解的使用,作者这里整理了一些笔记. 关于Mybatis @Pa ...

最新文章

  1. 注意力机制的本质中文版代码
  2. 上汽接入Momenta飞轮,成为中国第一个落地RoboTaxi的车企
  3. vim global命令
  4. java uppercase方法_Java toUpperCase()方法及其示例
  5. OpenStack 简介
  6. IDEA 2021.3 重磅发布!远程开发 (Beta) 、机器学习、故障自检、体验优化......
  7. 技术能变现,才是硬道理
  8. 错误:this is incompatible with sql_mode=only_full_group_by
  9. 电脑内存16g和32g,有什么区别?
  10. java项目中build path的设置
  11. ADT版本查看,This Android SDK requires Andr...ate ADT to the latest问题
  12. XJOI 7623 maoge数
  13. EXCEL的去重去除某个字段后全部操作
  14. java发送邮件被退回,从Java应用程序发送电子邮件中的异常:中继被拒绝
  15. C波段、KU波段与雨衰现象
  16. [我所知道的BIOS]-[Jumpless] 4
  17. 【CQBZOJ - 1205】因式分解问题
  18. Hive第二代客户端远程连接
  19. 写一个用矩阵法求定积分的通用函数,分别求sinx,cosx,exp(x)的定积分
  20. Flash 安装、修复和诊断工具分享(Flash大厅)

热门文章

  1. php html asp .net iis tomcat,iis+apache+tomcat 整合共享80口 支持ASP .NET JSP PHP全能WEB服务...
  2. java发送会议邀请邮件模板_Spring 发送邮件 HTML邮件
  3. 101. 对称二叉树023(BFS)
  4. 二分查找基础概念与经典题目(Leetcode题解-Python语言)二分数值型
  5. 探秘react,一文弄懂react的基本使用和高级特性
  6. mysql表缓冲大小可能设置过小_MySQL 5.7 my.cnf配置文件详解
  7. Java 源程序与编译型运行区别
  8. [MySQL基础]MySQL语法规范介绍
  9. 扫地机器人隔板_【扫地机器人使用】_摘要频道_什么值得买
  10. PHP自动判断用户会员过期,php,_定时扣除用户过期积分,但平台用户量比较大,有没有好的解决方法?,php - phpStudy...