MyBatis传递参数为集合时踩的坑

怎么回事#

这两天因为刚进组,拉到代码后用debug在了解项目的业务逻辑,其中有一个坑在当时让我百思不得其解,直到现在还有些疑问留在心中,所以打算写下来作为一个记录

既然是去了解业务逻辑,和数据库关联的操作肯定要重点关注。但是在使用postman发请求时,mybatis总是抛异常

org.apache.ibatis.binding.BindingException:Parameter '**'not found.Available parameters are[...]...

wtf?

看看代码咯#

mapper接口

// 怕被公司认出来,就对代码进行简单化处理,知道那么个意思就行
List<Object> getObjectsByIds(List<Integer> ids);

xml文件

<select id="getObjectsByIds" resultMap="baseResultMap">
    select id,name from test_table where id in
        <foreach collection="ids" item="id" open="(" separator="," close=")">
                #{id}
        </foreach>
</select>

这个功能其实很简单,就是传递一个id的list进去,根据id们去查询对应的object,乍一看没什么问题,但是有个地方却是踩坑的点

#

真正的坑需要同时结合接口和xml文件来看

List<Object> getObjectsByIds(List<Integer> ids)

<foreach collection="ids" item="id" open="(" separator="," close=")">

首先接口没加@Param注解,xml文件中直接将collection的值设置为ids,这里就不得不提一下mybatis在传递参数为集合时的机制了

首先看大家怎么说

collection属性必须指定,但是在不同情况下其值也不同
1. 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
2. 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
3. 如果如果传入的是单参数且参数类型是一个Set集合的时候,collection的属性值不知道是什么,
   遇到这种不知道的情况可以通过注解`@Param("set")`指定key值
4. 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map   实际上如果你在传入参数的时候,在MyBatis里面也是会把它封装成一个Map的,map的key就是参数名,
   所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key 

翻译翻译就是,如果在mapper接口传递的参数不加@Param,那么在xml中只能用它默认的属性值去接受,List就是list,Array就是array;如果在mapper接口中使用@Param指定了名称,那在xml中就可以使用自己定义的名称去接收了

所以刚刚报错的原因就是既没有用注解表明自定义的名称,又没在xml中用MyBatis默认的属性值

改起来有两种方式

修改方式一#

mapper接口

List<Object> getObjectsByIds(@Param("ids") List<Integer> ids);

xml文件

<select id="getObjectsByIds" resultMap="baseResultMap">
    select id,name from test_table where id in
        <foreach collection="ids" item="id" open="(" separator="," close=")">
                #{id}
        </foreach>
</select>

修改方式二#

mapper接口

List<Object> getObjectsByIds(List<Integer> ids);

xml文件

<select id="getObjectsByIds" resultMap="baseResultMap">
    select id,name from test_table where id in
        <foreach collection="list" item="id" open="(" separator="," close=")">
                #{id}
        </foreach>
</select>

总结#

两种修改方式都能让程序正常运行,但就我个人而言还是更喜欢方式一的修改,因为相比于参数在不同文件有不同名称,我还是更倾向于把所有名称都进行统一

多说一句#

我也查阅了一些资料,在MyBatis官方文档中并没有很明确的提及foreach中collection到底怎么赋值,倒是官方提供的实例确实也是用的list进行的接收

有趣的是,我在文中提到的文档是根据各个论坛中的文章进行总结而成的,如果说大家确实在官方那里看到说collection具有默认值也欢迎评论

剩余的疑问#

尽管在我这把程序跑起来不抛异常了,但是我同事那里代码和我修改之前一模一样,但是他那边就可以正常运行,这个问题有了解的朋友欢迎留言,感谢!(跪了)

posted @   colee51666  阅读(390)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
点击右上角即可分享
微信分享提示
主题色彩
哥伦布
15°
00:09发布
哥伦布
00:09发布
15°
中雨
西风
3级
空气质量
相对湿度
92%
今天
中雨
15°/22°
周一
中雨
6°/19°
周二
小雨
2°/10°