Mybatis 批量更新报错:Parameter 'orderList' not found. Available parameters are [collection, list]
项目中有个任务要处理数据库中十几万的数据,根据设置的评分项对订单进行打分,并更新打分和命中的评分项。
参考之前代码中的写法,创建递归线程池,将任务拆分成不大于 700 条记录的子任务,然后在子任务中遍历数据并处理。因为循环插入数据库是比较不推荐的做法,所以在遍历数据中,创建需要更新的数据对象并填充,然后添加到更新列表中,在遍历结束后批量更新。
前面遇到一些 null 空对象的错误,都一一修复了,主要就卡在了批量更新的 sql 上。项目中引入的是 tk-mybatis:2.1.5
,有批量插入的 insertList()
但没有批量更新的 sql,需要自定义。
百度 Mybatis 批量更新 AI 自动生成了 sql 的定义:
<update id="updateBatchRank" parameterType="java.util.List">
<foreach collection="orderList" item="item" index="index" separator=";">
UPDATE case_info
<trim prefix="SET" suffixOverrides=",">
<if test="rankScore != null">rank_score = #{item.rankScore},</if>
<if test="rankTag != null">rank_tag = #{item.rankTag},</if>
</trim>
WHERE id = #{item.id}
</foreach>
</update>
但在试执行的时候报错:Parameter 'orderList' not found. Available parameters are [collection, list]
。有点看不明白,在看了 Parameter 'xxx' not found. Available parameters are [collection, list] - cnblogs 才意识到,原来是传递参数没有标记。
正常查询要么是简单的 Integer 或者 String 类型,要么就是一个实体类的对象。实体类一般不标注 @Param("xxx")
参数,然后在 sql 中可以直接使用实体类对象的属性。而基础的类型参数可加可不加,sql 中使用的参数名与传入参数一致。而 List 显然不是简单类型,如果想要使用参数名,就要标注出来。
修改 Mapper 接口中的定义方法:
int updateBatchRank(@Param("orderList") List<Order> orderList);
此外,还可以将 sql 中 Collection="orderList"
改为 Collection="list"
或者 Collection="collection"
,如果参数是数组则改为 Collection="array"
。
测试标注参数,或者修改 Collection 名两种方法都可以。
之后遇到报错:Parameter 'rankScore' not found. Available parameters are [orderList, param1]
。一开始以为是 item.rankScore
获取不到值,但网上的例子都表示可以这样用。最后才发现原来是 if 判断里的变量不对,应该改成 item.rankScore
。
<update id="updateBatchRank" parameterType="java.util.List">
<foreach collection="orderList" item="item" index="index" separator=";">
UPDATE case_info
<trim prefix="SET" suffixOverrides=",">
<if test="item.rankScore != null">rank_score = #{item.rankScore},</if>
<if test="item.rankTag != null">rank_tag = #{item.rankTag},</if>
</trim>
WHERE id = #{item.id}
</foreach>
</update>
在执行的时候又报错:Parameter index out of range (31 > number of parameters, which is 30).
,大概的意思是,参数索引大于参数个数。
百度了一下,原来是我有部分的 sql 使用 #
注释了,然后将其中的注释部分去掉就好了。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。