mysql之批量操作foreach用法

1、批量查询

<select id="selectAllItemsByIds" parameterType="java.util.List" resultMap="BaseResultMap">
    select
    id, field1, field2
    from item_info
    <where>
        id in
        <foreach collection="list" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
    </where>
</select>

2、批量删除

<delete id="deleteUsersByNames" parameterType="java.util.List">
   delete from item_info
   where username in
   <foreach collection="list" item="item" open="(" separator="," close=")">
       #{item}
   </foreach>
</delete>

3、批量更新

<update id="updateItemsById">
    <foreach collection="list" item="item" index="index" open="" close="" separator=";">
        UPDATE item_info
        <set>
            field1 = #{item.field1}
        </set>
        WHERE id = #{id}
    </foreach>
</update>

4、批量插入

<insert id="insertItemsByBatch" parameterType="java.util.List">
  insert into item_info (id,field1,field2)
  values
  <foreach collection="list" item="item" index="index" separator=",">
    (
	    #{item.id,jdbcType=BIGINT},
	    #{item.field1,jdbcType=VARCHAR},
	    #{item.field2,jdbcType=VARCHAR}
    )
  </foreach>
</insert>
<think>嗯,用户遇到了一个MyBatis的异常,说Mapper方法返回了null,而方法声明的是int类型,导致类型转换错误。用户提供的SQL XML片段是一个update语句,里面用了foreach循环来更新多个记录。现在需要分析为什么这个update会返回null。 首先,我得回忆一下MyBatis的update操作默认的返回值是什么。通常来说,MyBatis的update、insert、delete语句默认返回的是受影响的行数,也就是int类型。如果数据库没有更新任何行,应该返回0,而不是null。所以用户这里返回null,显然是不正常的。 接下来,看看用户提供的XML配置。select标签的id是updateVersion,但是里面写的是update语句。这里可能有问题,因为MyBatis中,update操作应该使用<update>标签,而不是<select>。使用错误的标签可能导致MyBatis错误地处理返回值,比如当成查询语句来执行,而查询可能返回null,特别是当没有结果集的时候。所以这个标签错误可能是关键原因。 然后,检查SQL语句本身。这个update语句是批量更新,根据code列表来设置version。如果传入的codes列表为空,或者数据库中没有匹配的记录,这时候受影响的行数应该是0,而不是null。但是用户得到的是null,所以可能不是数据的问题,而是配置或执行的问题。 另一个可能性是数据库驱动的问题。某些情况下,数据库驱动可能在执行update时返回null,特别是在有错误或警告的情况下,但通常这应该抛出异常而不是返回null。不过用户没有提到异常,所以可能不是这种情况。 另外,用户可能错误地在update语句中配置了resultType,比如指定了某个包装类型,导致MyBatis试图映射结果,但update的返回值本来就是int,不需要resultType。不过用户提供的XML中没有显示resultType属性,所以这个可能性较低,除非用户省略了部分配置。 总结一下,最可能的问题是用户错误地使用了<select>标签来包裹update语句。因为select通常用于查询,返回结果集,而如果没有结果集,可能会返回null。而update应该使用<update>标签,这样MyBatis会正确处理返回值,返回受影响的行数,即使为0也会返回0而不是null。 解决方案就是把<select>标签改成<update>标签,这样MyBatis就能正确返回受影响的行数,避免返回null导致类型转换错误。同时,确保传入的codes列表不为空,或者即使为空,SQL语句也能正确执行,不影响返回值。</think>让我们逐步分析这个SQL映射语句的问题根源: --- ### **直接问题定位** ```xml <!-- 错误点:错误使用<select>标签包裹UPDATE语句 --> <select id="updateVersion"> update mz_outpatientlist set version = #{newVersion} where code in <foreach collection="codes" item="item" open="(" separator="," close=")"> #{item} </foreach> </select> ``` --- ### **错误机制解析** ```mermaid graph TD A[<select>标签] --> B[MyBatis按查询操作处理] B --> C{试图返回ResultSet} C -->|UPDATE无结果集| D[返回null] D --> E[Mapper方法声明为int] E --> F[无法赋值null给基本类型] F --> G[抛出类型转换异常] ``` --- ### **修复方案** **步骤1:修正SQL标签类型** ```xml <!-- 使用正确的<update>标签 --> <update id="updateVersion"> update mz_outpatientlist set version = #{newVersion} where code in <foreach collection="codes" item="item" open="(" separator="," close=")"> #{item} </foreach> </update> ``` **步骤2:验证代码逻辑** 1. 检查传入的`codes`集合是否为空 2. 确保`newVersion`参数有效 3. 添加空集合保护: ```java // 在调用Mapper前添加校验 if (CollectionUtils.isEmpty(codes)) { throw new IllegalArgumentException("codes列表不能为空"); } ``` --- ### **深度原理说明** | MyBatis标签类型 | 预期行为 | 返回值处理逻辑 | |----------------|-------------------------|--------------------------------| | `<select>` | 执行DQL(查询) | 尝试映射结果集,无结果时返回null | | `<update>` | 执行DML(增删改) | 直接返回受影响行数(int类型) | --- ### **典型错误场景验证** **场景1:空集合导致的异常** ```java // 当codes为空时,SQL等价于: update mz_outpatientlist set version = ? where code in () ``` * 解决方法:添加空集合校验 **场景2:数据库连接器行为差异** * MySQL驱动:空IN列表会报语法错误 * PostgreSQL驱动:空IN列表等效于`false`,返回0行 * Oracle:直接拒绝执行 --- ### **补充建议** 1. 启用MyBatis完整日志: ```yaml # application.yml mybatis: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl ``` 2. 添加SQL执行监控: ```sql -- 在MySQL中检查最后一次影响行数 SELECT ROW_COUNT(); ``` --- **最终结论**:错误根源在于错误使用`<select>`标签包裹UPDATE语句,导致MyBatis试图解析不存在的查询结果集。将标签改为`<update>`即可立即修复此问题。同时建议补充空参数校验,避免生成无效SQL。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

书生伯言

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值