项目中有个任务要处理数据库中十几万的数据,根据设置的评分项对订单进行打分,并更新打分和命中的评分项。

参考之前代码中的写法,创建递归线程池,将任务拆分成不大于 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 使用 # 注释了,然后将其中的注释部分去掉就好了。