使用JPA时,报错Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1

参考文章:SpringBoot系列教程JPA之delete使用姿势详解

出现问题的场景

在两个线程中的异步方法里,都调用delete方法删除同一条数据,而这条数据在库中是存在的,大概率会出现该异常。

原因

JPA在delete某条数据时,实际上是按照条件先select这条数据,然后再delete这条数据by主键id。即先根据条件find出该条数据对应的主键id,然后deleteById删除该条数据。
源码中,JPA实际上调用SimpleJpaRepository中的deleteById()方法。

@Transactional
public void deleteById(ID id) {Assert.notNull(id, ID_MUST_NOT_BE_NULL);delete(findById(id).orElseThrow(() -> new EmptyResultDataAccessException(String.format("No %s entity with id %s exists!", entityInformation.getJavaType(), id), 1)));
}@Transactional
public void delete(T entity) {Assert.notNull(entity, "The entity must not be null!");em.remove(em.contains(entity) ? entity : em.merge(entity));
}

推测出现该问题的原因是两个线程都delete,根据JPA的原理,相当于四条语句,两条查询两条删除。而JPA是用不同的队列存不同的操作,当两个线程均先执行select然后再delete时,第二个delete删除时,原本查出来一条数据,应该删除这条数据,但实际上删除了0条数据,因为该条数据已经被第一个delete删除了,导致预期和实际不匹配,会抛出该异常:Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1。

如下图所示,若是两个线程先select完了,再delete就会报错,如果两个线程按顺序一个先删一个后删,就不会有错误。

本来想在执行delete后,flush一下,但是并没有用。即使flush,如图第一种情况还是回报错。

解决方法

使用原生sql语句执行,不使用jpa就可以了。

@Transactional
@Modifying
@Query(value = "delete from user where name =:name ",nativeQuery = true)
void deleteByName(@Param("name") String name);

解决Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1的一种方法相关推荐

  1. Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1;

    Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; 数据库表的i ...

  2. org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actua

    hibernate更新数据的时候,如果数据不存在,就报org.hibernate.StaleStateException: Batch update returned unexpected row c ...

  3. JPA 异常Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1

    这个错误,看了网上大部分的贴子都说是主键自增设了值问题,但是我的主键非自增的手动赋值了,也出现此错误,原因如下: JPA使用 save更新数据的时候,如果数据没有任何变化也会报错,我们翻译一下这个错误 ...

  4. org.hibernate.StaleStateException:Batch update returned unexpected row count from update [0]; actua

    解决办法 <generator class="native"/>中的class由原来的"native"设置为"assigned" ...

  5. SSH开发中 使用超链接到action 其excute方法会被执行两次 actual row count: 0; expected: 1...

    由于执行两次excute,所以在做删除操作的时候会出现 Batch update returned unexpected row count from update [0]; actual row c ...

  6. 5种方法完美解决android软键盘挡住输入框方法详解

    版权声明:本文为CSDN博主「潇潇凤儿」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明. 原文链接:https://blog.csdn.net/smileiam/ ...

  7. 解决 git clone fatal: unable to access ‘https://github.com...‘: 的一种方法

    解决 git clone fatal: unable to access 'https://github.com-': Could not resolve host: github.com的一种方法 ...

  8. 前端解决移动端适配的五种方法

    移动端适配的五种方法 所谓移动端适配,就是WebApp在不同尺寸的屏幕上等比显示 第一种方法:viewport适配 原理:通过设置 initial-scale , 将所有设备布局视口的宽度调整为设计图 ...

  9. element 手机适配_解决手机移动端适配的五种方法

    移动端适配的五种方法 所谓移动端适配,就是WebApp在不同尺寸的屏幕上等比显示 第一种方法:viewport适配 原理:通过设置 initial-scale , 将所有设备布局视口的宽度调整为设计图 ...

最新文章

  1. thinkphp无法加载模块解决办法
  2. 开发中经常碰到的问题cookie和session问题,今天一并解决
  3. 20211004 矩阵的子空间
  4. 高通平台smd分析及smem共享内存的创建笔记
  5. MySQL知识总结(二)基本语句总结
  6. P4309 [TJOI2013]最长上升子序列 平衡树 + dp
  7. Python自制微信机器人:群发消息、自动接收好友
  8. 结构与算法(05):二叉树与多叉树
  9. Matlab程序仿真与调试入门
  10. c语言输出字符串长度 空格,C++指针变量:输入一个字符串,删除字符串中所有空格,输出删除空格后字符串的长度,需编写以下功能函数...
  11. java读取图片成rgb二维数组
  12. rest_framework-序列化-总结完结篇
  13. SQL笛卡尔积查询的典型应用
  14. 苹果手机温度测试软件,苹果手机测温神器上线啦!
  15. mac 外接双显示器
  16. 计算机怎么转换中文版,电脑转换中文是哪个键
  17. 记录虚拟机中更改虚拟网络编辑器无效的解决方法
  18. Linux中使用grep -v grep 查找不含有 grep 字段的行
  19. Android Studio Chipmunk | 2021.2.1 JNI
  20. UltraEdit软件破解方法

热门文章

  1. 飞天遁地、来去自如?Oracle数据库秉承技术当先,用户也来说说看
  2. 爬取豆瓣读书-豆瓣成员常用的标签(Python爬虫实战)
  3. 信息系统项目管理师是哪个部门发证?
  4. Python绘图制作混淆矩阵图--简易版(改矩阵参数就能运行)
  5. zabbix迁移部署注意事项
  6. 2021年11月15日到2021年11月21日笔记
  7. 【独家专访】谭龙喊话同行:几个月后 ETCP将不可超越
  8. 远程服务器 一闪就没有了,远程桌面连接一闪而过的解决方法
  9. python while true try except_Python为true时,Try/Except,返回valu
  10. 关于win10系统重置后出现鼠标右键桌面一直转圈问题的解决办法