sql update操作数据更新成功,返回的影响行数是0

       
       以前使用sql server, mysql时候,本能以为update操作返回的行数能判断对记录的操作结果,除了数据库异常,一般确实能反应操作的真实情况,但是,为何却出现update数据更新成功,反而返回影响行数为0的情况呢?
以为可以判断返回值是否大于0来判断更新是否成功,但是,下面的两种情况均返回0:
       1、没有找到需要更新的数据
             比如,我们进行update的时候,条件是id=5,但是id=5的数据不存在。这种情况下,更新是失败的,返回0,很正确;
       2、要更新的数据和更新的值是完全一样的
             比如,我们要对id=5的记录进行更新,把title变成hello。虽然这条记录存在,但是这条记录的title本来就是hello,那么,返回值也是0;
       3、本身写的sql语句有问题
             比如,update test set cid = ‘5244’ where cid is null or cid=‘’;
       第一种情况可以快分析到,但是调查发现不是这种问题,第二种和第三种为啥会出现这样的问题呢? 调查日志发现,同一时间接受到了两条数据导致了二三的出现,所以,大家在碰到这样的问题的时候,看看是不是因为并发请求导致的。控制好自己的并发事物,不然就会怀疑update的这个操作喽~

重大补充:最近发现update操作使用返回的的影响行数来判断操作成功与否,有时候还与第三方持久化框架有关
       使用原生的sql(或者mysql) 重复请求update操作的时候,如 update test set cid = ‘5244’;执行两次的时候发现,update返回影响行数为0。但是使用mybatis的时候,结果却不是这样的,执行两次的时候,发现update返回的影响行数始终是1。后面跟踪发现,原来mybatis这个第三方持久化框架返回来的是被匹配的影响行数,所以返回的始终是1,那如果想要以返回的行数作为判断结果,需要在mybatis连接数据库的时候加上参数:jdbc:mysql://${jdbc.host}/${jdbc.db}?useAffectedRows=true

 

<think>嗯,用户现在问的是关于MyBatis中XML update语句返回成功行数的问题。我需要先回忆一下之前讨论过MyBatis的updateById方法如何处理逻辑删除字段,但现在的问题更基础,是关于update操作返回行数。 首先,用户可能在使用MyBatis执行更新操作时,想知道如何获取受影响行数。或者他们可能遇到了更新语句执行后返回行数与预期不符的情况。比如,即使没有实际更新数据返回行数是否是1或者0,这取决于数据库的实现和配置。 接下来,我需要确认MyBatis的update方法默认返回的是什么。根据知识,MyBatis的update方法(包括insert和delete)返回的是受影响行数,也就是被成功修改的记录数。这个值通常由JDBC的Statement.executeUpdate()方法返回,MyBatis会把这个值直接返回给调用者。 但用户可能遇到的问题是,为什么有时候即使没有实际修改数据(比如更新的字段值和原来一样),返回值可能还是1。这时候需要解释数据库的行为,比如MySQL在默认配置下,即使数据没有变化,update语句也会返回匹配的行数,而不是实际受影响行数。而如果启用了useAffectedRows属性,MySQL返回实际被修改的行数。 此外,用户可能在XML映射文件中编写update语句,这时候需要确认是否在标签中有设置相关属性,比如flushCache、useGeneratedKeys等,但这些通常不影响返回行数返回行数主要取决于数据库驱动返回的值。 用户还可能问到如何在代码中获取这个返回值。比如在Mapper接口中定义一个返回int的方法,调用该方法后就能得到受影响行数。这时候需要给出示例代码,比如Mapper接口中的方法定义,以及如何在Service层中使用这个返回值。 另外,可能存在特殊情况,比如使用乐观锁(如MyBatis-Plus的@Version注解),此时更新操作可能会影响返回值,因为每次更新版本号会变化,从而影响匹配的行数。这时候需要区分MyBatis原生和MyBatis-Plus的不同处理方式。 还需要考虑事务的影响,如果在事务中多次执行update返回值会是每次操作影响行数,但最终是否提交事务也会影响实际数据库的变化。但返回行数是在执行时即确定的,不管事务是否提交。 用户可能还会混淆affected rows和matched rows的概念,需要解释清楚。比如,在MySQL中,默认返回的是matched rows,而开启useAffectedRows后返回实际变化的行数。这可能影响业务逻辑的判断,比如判断是否成功更新数据。 最后,总结一下,MyBatis的XML update语句返回的是数据库驱动返回的受影响行数,具体值取决于数据库的配置和SQL语句的执行情况。需要根据具体情况调整数据库配置或SQL语句,以确保返回行数符合业务需求。</think>MyBatis中XML配置的update语句**默认返回影响行数**(即成功修改的记录数),具体行为可通过以下维度解析: --- ### 一、返回值本质 ```java // Mapper接口定义 int updateUser(User user); // 调用示例 int affectedRows = userMapper.updateUser(user); ``` *返回值数据库驱动报告的受影响行数(JDBC的`Statement.executeUpdate()`返回值)* --- ### 二、核心影响因素 | 影响因素 | 说明 | |---------------------------|----------------------------------------------------------------------| | **SQL匹配条件** | WHERE子句筛选出的记录数 | | **数据库配置** | MySQL需注意`useAffectedRows`参数(控制返回匹配行数还是实际修改行数) | | **触发器/级联更新** | 其他数据操作可能影响最终返回值 | | **乐观锁冲突** | 使用`@Version`时版本号不匹配会导致返回0 | --- ### 三、典型场景分析 #### 场景1:基础更新 ```xml <update id="updateName"> UPDATE users SET name=#{name} WHERE id=#{id} </update> ``` *返回1(找到并修改了记录)或0(未找到匹配记录)* #### 场景2:批量更新 ```xml <update id="batchUpdateStatus"> UPDATE orders SET status=#{status} WHERE create_time < #{expireDate} </update> ``` *返回所有符合条件的记录数(如更新了5条订单则返回5)* --- ### 四、MySQL特殊配置 ```ini # jdbc连接串添加参数(默认false) jdbc:mysql://localhost:3306/db?useAffectedRows=true ``` | 参数状态 | 行为 | |----------------------|--------------------------------| | useAffectedRows=false | 返回WHERE匹配的行数(默认值) | | useAffectedRows=true | 返回实际数据发生变更的行数 | *示例:将已存在值`name='张三'`的记录再次更新为`name='张三'`时:* - 关闭参数 → 返回1 - 开启参数 → 返回0 --- ### 五、返回值验证技巧 1. **日志查看** 启用MyBatis SQL日志观察实际执行情况: ```yaml mybatis: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl ``` 2. **单元测试断言** ```java @Test void testUpdate() { User user = new User(1, "NewName"); int result = userMapper.updateUser(user); assertThat(result).isEqualTo(1); } ``` --- ### 六、特殊案例处理 #### 案例:乐观锁冲突 ```java public class Product { @Version private Integer version; // 乐观锁字段 } ``` *当版本号不匹配时,更新操作返回0* #### 案例:触发器影响 ```sql -- 创建修改其他表的触发器 CREATE TRIGGER log_update AFTER UPDATE ON users FOR EACH ROW BEGIN INSERT INTO audit_log VALUES(NOW(), 'User updated'); END; ``` *触发器操作**不会**改变原update语句返回值,仍返回users表的受影响行数* --- ### 七、最佳实践 1. **关键操作校验** ```java if (affectedRows == 0) { throw new BusinessException("更新失败,记录不存在或数据未变更"); } ``` 2. **MySQL生产建议** 启用`useAffectedRows=true` + 连接池配置: ```yaml datasource: url: jdbc:mysql:///db?useAffectedRows=true&rewriteBatchedStatements=true ``` 3. **PostgreSQL注意** 该数据库默认返回实际修改行数,无需特殊配置 --- **总结**:MyBatis的XML update返回值直接反映数据库层面的操作结果,需结合具体SQL数据库配置理解其含义,关键业务建议配合版本号或条件验证确保数据一致性。
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值