5.10 mybatis之useActualParamName作用

文章目录

  • 1. useActualParamName=false
    • 1.1 单个参数映射
    • 1.2 多个数
    • 1.3 param注解
  • 2. useActualParamName=true

useActualParamName官方解释:允许使用方法签名中的名称作为语句参数名称。 为了使用该特性,你的项目必须采用 Java 8
编译,并且加上 -parameters 选项。(新增于
3.4.1)。useActualParamName有2个值,true和false,如不配置默认为true。

如何理解这句话呢?

假如DAO接口方法中传入的参数名为personId,那么在mapper文件中也想通过#{personId}方式获取参数personId的值,那么需要在mybatis的settings配置中添加useActualParamName=true配置(当然默认为true),并且JDK8以上编译器,并且编译时添加-parameters 选项。

如还不理解,我们继续看下面示例,首先看下useActualParamName=false情况

1. useActualParamName=false

首先在springboot的application.yml文件中添加mybatis的如下配置, 主要是设置use-actual-param-name=false关闭dao方法参数名直接作为mapper文件中SQL的参数名。

mybatis:mapper-locations: classpath*:mapper/*Mapper.xmlconfiguration:cache-enabled: trueuse-actual-param-name: false

1.1 单个参数映射

下面以person表为例,如下所示,表中含有2条数据。
在这里插入图片描述
假设需要查询person_id=14的一条数据,mapper中对应的SQL如下所示,需要获取参数名为personId的值

<resultMap id="resultMap1" type="com.lzj.bean.Person"><result column="PERSON_ID" property="id"></result><result column="PERSON_NAME" property="name"></result><result column="PERSON_SEX" property="sex" javaType="com.lzj.bean.SexEnum"></result><result column="PERSON_AGE" property="age"></result>
</resultMap>
<select id="select1" resultMap="resultMap1">select * from PERSON where PERSON_ID = #{personId}
</select>

对应的DAO接口如下所示,但是接口中传入的参数名为id,显然与mapper中需要的参数名为personId不一致,下面看一下会怎么样

public interface PersonDao {public List<Person> select1(int id);
}

创建测试案例如下所示

@Component
public class PersonService {@Autowiredprivate PersonDao personDao;public void query1(){List<Person> persons = personDao.select1(14);System.out.println(persons);}

启动该测试案例,输出结果如下所示,说明:当只有一个输入参数时,即使DAO接口中参数名与mapper中获取的参数名不一致,DAO 中的参数可以正确到映射到mapper中的参数上,mybatis能正确取到值并执行成功。

2024-04-15 23:09:51.159  INFO 11120 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8004 (http) with context path ''
2024-04-15 23:09:51.177  INFO 11120 --- [           main] com.lzj.MyServiceTest                    : Started MyServiceTest in 8.379 seconds (JVM running for 10.385)
2024-04-15 23:09:51.229  INFO 11120 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2024-04-15 23:09:52.240  INFO 11120 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2024-04-15 23:09:52.257 DEBUG 11120 --- [           main] com.lzj.dao.PersonDao.select1            : ==>  Preparing: select * from PERSON where PERSON_ID = ? 
2024-04-15 23:09:52.393 DEBUG 11120 --- [           main] com.lzj.dao.PersonDao.select1            : ==> Parameters: 14(Integer)
2024-04-15 23:09:52.771 DEBUG 11120 --- [           main] com.lzj.dao.PersonDao.select1            : <==      Total: 1
[Person{id=14, name='Tom', sex=SexEnum{description='男性'}, age=25}]

1.2 多个数

前面一个案例是单个输入参数的情况,那么当输入多个参数时会是什么情况呢?
还是以前面库表为例,假设需要查询person_id=14并且person_age=25的数据,对应的mapper 如下所示

<select id="select3" resultMap="resultMap1">select * from PERSON where PERSON_ID = #{personId} and PERSON_AGE = #{personAge}
</select>

对应的Dao接口如下所示,我们设置dao方法入参与mapper文件中select3的SQL入参一致,继续观察是否还能正确把值从dao传入到mapper中

public interface PersonDao {public List<Person> select3(int personId, int personAge);
}

执行如下测试案例

public void query2(){List<Person> persons = personDao.select3(14, 25);System.out.println(persons);
}

结果竟然报错了,本次dao接口中参数名与mapper中参数名完全保持一致竟然还没有正确执行,就是因为设置了useActualParamName=false,DAO中传入的参数名分别为personId和personAge,而传递到mybatis后参数名并不再是personId和personAge。

Exception in thread "main" org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.binding.BindingException: Parameter 'personId' not found. Available parameters are [0, 1, param1, param2]at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:77)at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446)at com.sun.proxy.$Proxy49.selectList(Unknown Source)at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:230)at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:147)at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:80)at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:57)at com.sun.proxy.$Proxy50.select3(Unknown Source)at com.lzj.service.PersonService.query2(PersonService.java:22)at com.lzj.MyServiceTest.main(MyServiceTest.java:16)
Caused by: org.apache.ibatis.binding.BindingException: Parameter 'personId' not found. Available parameters are [0, 1, param1, param2]at org.apache.ibatis.binding.MapperMethod$ParamMap.get(MapperMethod.java:212)at org.apache.ibatis.reflection.wrapper.MapWrapper.get(MapWrapper.java:45)at org.apache.ibatis.reflection.MetaObject.getValue(MetaObject.java:122)at org.apache.ibatis.executor.BaseExecutor.createCacheKey(BaseExecutor.java:219)at org.apache.ibatis.executor.CachingExecutor.createCacheKey(CachingExecutor.java:146)at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:82)at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:147)at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:483)at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:433)... 8 more

下面我们通过断点看一下,dao中参数传递到mapper中变成了啥样,我们看断点的parameter参数,发现mapper要想成功取得参数,需要通过0和1占位符的形式获取参数值,或者通过param1或者param2的方式获取参数值。
在这里插入图片描述
比如我们把mapper修改成占位符为0和1的情况如下所示

<select id="select3" resultMap="resultMap1">select * from PERSON where PERSON_ID = #{0} and PERSON_AGE = #{1}
</select>

再执行上面测试案例则成功输出如下所示

…………………………省略启动日志
2024-04-16 00:12:24.055  INFO 8528 --- [           main] com.lzj.MyServiceTest                    : Started MyServiceTest in 5.495 seconds (JVM running for 6.468)
2024-04-16 00:12:24.081  INFO 8528 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2024-04-16 00:12:24.641  INFO 8528 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2024-04-16 00:12:24.656 DEBUG 8528 --- [           main] com.lzj.dao.PersonDao.select3            : ==>  Preparing: select * from PERSON where PERSON_ID = ? and PERSON_AGE = ? 
2024-04-16 00:12:24.698 DEBUG 8528 --- [           main] com.lzj.dao.PersonDao.select3            : ==> Parameters: 14(Integer), 25(Integer)
2024-04-16 00:12:24.729 DEBUG 8528 --- [           main] com.lzj.dao.PersonDao.select3            : <==      Total: 1
[Person{id=14, name='Tom', sex=SexEnum{description='男性'}, age=25}]

1.3 param注解

那么对于多个传参情况,mapper中参数名如若与dao接口方法中参数名保持一致,该如何操作呢?大家经常用的@Param注解就登场了。
还是以上面的案例,dao接口方法的参数前面添加@Param注解,如下所示

public interface PersonDao {public List<Person> select3(@Param("personId") int personId, @Param("personAge") int personAge);
}

mapper中通过#{personId}和#{personAge}获取参数值

<select id="select3" resultMap="resultMap1">select * from PERSON where PERSON_ID = #{personId} and PERSON_AGE = #{personAge}
</select>

重新启动上面测试案例,正确输出结果如下所示

………………省略启动日志
2024-04-16 00:16:51.404  INFO 11772 --- [           main] com.lzj.MyServiceTest                    : Started MyServiceTest in 5.792 seconds (JVM running for 6.766)
2024-04-16 00:16:51.447  INFO 11772 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2024-04-16 00:16:52.452  INFO 11772 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2024-04-16 00:16:52.460 DEBUG 11772 --- [           main] com.lzj.dao.PersonDao.select3            : ==>  Preparing: select * from PERSON where PERSON_ID = ? and PERSON_AGE = ? 
2024-04-16 00:16:52.500 DEBUG 11772 --- [           main] com.lzj.dao.PersonDao.select3            : ==> Parameters: 14(Integer), 25(Integer)
2024-04-16 00:16:52.534 DEBUG 11772 --- [           main] com.lzj.dao.PersonDao.select3            : <==      Total: 1
[Person{id=14, name='Tom', sex=SexEnum{description='男性'}, age=25}]

下面我们还是断点一下,DAO接口方法传入的参数传递到mybatis被映射成什么参数了。我们发现Dao中参数名personId和personAge映射到mapper中参数名除了personId和personAge,还有param1和param2,所以在mapper中除了可以用#{personId}和#{personAge}形式,还是可以继续用#{param1}和#{param2}形式,这一点与前面案例相同。
在这里插入图片描述

2. useActualParamName=true

上面一案例已演示可以通过@param注解的方式保持DAO中参数名与mapper中参数名一致,假设有大量的DAO接口以及大量的方法,那么每一个接口中每一个方法的每个参数都要用注解注释一遍,非常繁琐,那么如何简化这一状况呢?

下面就引出了本文的重点,对于mybatis版本大于3.4.1,且java用的JDK8以上,并且编译是添加-parameters参数(比如用idea运行的代码,需要在idea工具中配置;如果用maven编译的,那么需要在编译命令中添加-parameters)。

另外如果使用的spring boot 2.0及以后版本,并且依赖了 spring-boot-starter-parent组件,默认情况启用了-parameter参数,因此无需再刻意配置。dao中参数传入的什么名字,在mapper中直接获取相同的参数名即可。我们通过下面示例验证

首先修改mybatis的配置 如下所示,或者不配置use-actual-parm-name参数,因为默认就为true

mybatis:mapper-locations: classpath*:mapper/*Mapper.xmlconfiguration:cache-enabled: trueuse-actual-param-name: true

修改Dao方法如下所示,删除方法参数前面的@Param注解

public interface PersonDao {public int insert(Person person);public List<Person> select1(int id);public Map select2(int personId);public List<Person> select3(int personId, int personAge);
}

mapper中SQL与前面保持一致,直接通过personId和personAge参数名获取传入的值

<select id="select3" resultMap="resultMap1">select * from PERSON where PERSON_ID = #{personId} and PERSON_AGE = #{personAge}
</select>

下面spring boot使用2.3.11版本,mybatis使用3.5.2版本,重新启动前面测试案例,输出结果如下所示,正确执行,并输出了库表中数据。

……………………省略
2024-04-16 23:11:35.596  INFO 18012 --- [           main] com.lzj.MyServiceTest                    : Started MyServiceTest in 6.627 seconds (JVM running for 7.951)
2024-04-16 23:11:35.626  INFO 18012 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2024-04-16 23:11:36.182  INFO 18012 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2024-04-16 23:11:36.193 DEBUG 18012 --- [           main] com.lzj.dao.PersonDao.select3            : ==>  Preparing: select * from PERSON where PERSON_ID = ? and PERSON_AGE = ? 
2024-04-16 23:11:36.241 DEBUG 18012 --- [           main] com.lzj.dao.PersonDao.select3            : ==> Parameters: 14(Integer), 25(Integer)
2024-04-16 23:11:36.302 DEBUG 18012 --- [           main] com.lzj.dao.PersonDao.select3            : <==      Total: 1
[Person{id=14, name='Tom', sex=SexEnum{description='男性'}, age=25}]

我们继续断点一下,观察下dao中参数传递到mybatis中参数名时什么。发现当useActualParamName=true时,无须使用@Param注解,在mapper中依然可以可以通过dao中参数名personId和personAge获取掺入的参数值。当然也还可以继续通过param1和param2获取参数值,这一点与useActualParamName=false相同。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/625127.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux内核之aligned用法实例(四十七)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

KaiwuDB CTO 魏可伟:AIoT,用行业定义数据库

4月12日&#xff0c;由中国 DBA 联盟&#xff08;ACDU&#xff09;与墨天轮社区联合主办的第十三届数据技术嘉年华&#xff08;DTC 2024&#xff09;于北京盛大召开。KaiwuDB CTO 魏可伟受邀发表《智创当下&#xff0c;KaiwuDB 从多模到 AI 的探索实践》主题演讲&#xff0c;向…

看图找LOGO,基于YOLOv8全系列【n/s/m/l/x】参数模型开发构建生活场景下的商品商标LOGO检测识别系统

日常生活中&#xff0c;我们会看到眼花缭乱的各种各样的产品logo&#xff0c;但是往往却未必能认全&#xff0c;正因为有这个想法&#xff0c;这里我花费了过去近两周的时间采集和构建了包含50种商品商标logo的数据集&#xff0c;基于YOLOv8全系列的参数模型开发构建了对应的检…

2016NOIP普及组真题 1. 金币

线上OJ&#xff1a; 一本通&#xff1a;http://ybt.ssoier.cn:8088/problem_show.php?pid1969 核心思想&#xff1a; 解法1、由于数据量只有 10000 天&#xff0c;估可以采用 模拟每一天 的方式。 #include <bits/stdc.h> using namespace std;int k 0;int main() {i…

地质灾害监测预警系统:科技守护,构筑智能预警屏障

随着全球气候变化和人为活动的加剧&#xff0c;地质灾害频繁发生&#xff0c;给人们的生命财产安全带来了严重威胁。为了降低地质灾害带来的损失&#xff0c;地质灾害监测预警系统应运而生。本文将为您详细介绍地质灾害监测预警系统的原理、功能以及在实际应用中的效果。 一、地…

如何从零开始创建React应用:简易指南

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

C#通用类库封装实战

数据库查询 特性方式获取数据库列的别名 数据库更新 使用简单工厂配置的方式

企业邮箱迁移是什么?如何通过IMAP/POP协议进行邮箱迁移?

使用公司邮箱工作的过程中&#xff0c;公司可能遇到公司规模的扩大或技术架构升级&#xff0c;可能要换公司邮箱。假如马上使用新的公司邮箱&#xff0c;业务处理要被终断。企业邮箱转移是公司更换邮箱不可或缺的一步&#xff0c;不仅是技术操作&#xff0c;更是企业信息安全、…

【央国企专场】——军工研究所

研究所目录 一、企业概述1.1 中国航天1.2 中国电科1.3 中国船舶1.4 中国兵器 二、招聘信息2.1 中国航天2.2 中国电科2.3 中国船舶2.4 中国兵器 一、企业概述 在校招中会有很多企业来学校开宣讲会&#xff0c;其中就有许多广为人知的军工研究所&#xff0c;比如&#xff1a;中国…

“中医显示器”是人体健康监测器

随着科技的进步&#xff0c;现代医学设备已经深入到了人们的日常生活中。然而&#xff0c;在这个过程中&#xff0c;我们不应忘记我们的医学根源&#xff0c;中医。我们将中医的望、闻、问、切四诊与现代科技相结合&#xff0c;通过一系列的传感器和算法将人体的生理状态以数字…

GPT 浅析

GPT 浅析 文章目录 GPT 浅析GPT 1无监督预训练有监督微调任务相关的输入变换 GPT2GPT3 GPT 1 在模型架构上&#xff0c;GPT-1基于Transformer构造&#xff0c;这是因为与其他卷积神经网 络或者循环神经网络相比&#xff0c;Transformer提供了效率更高的方法来处理文本 中的长期…