Hibernate多事务同时调用update(T t) ,字段被覆盖问题

前言

今天现网有个订单卡单了,经过排查发现没有任何异常日志,根据日志定位发现本应该更新的一个状态,也sql肯定执行了(使用了Hibernate的ORM框架),但是数据库里面的状态没有更新。大概逻辑如下

String hql= from orderInfo where id="PTTest";
OrderInfo orderInfo=commomDao.findSingle(hql);
orderInfo.setStatus("completed");
commonDao.update(orderInfo);

根据日志能确认,此段代码肯定是被执行了,但是数据库表的Status依旧是processing。

问题排查

这种情况,怀疑是在Status更新成completed之后,其他的事务把Status更新了成processing了。想佐证这种猜测,直接看数据库的bin log日志是最直观的。找大数据组同事找了日志时间点周围的bin log日志

确实在更新completed之后,又被其他事务更新成processing。后来从ELK中查看到对应requestLog日志,发现确实有请求更新了Status。

问题解决

直接用update 语句更新需要更新的字段

update orderInfo set Status="completed" where id="PTTest";

这种写法,更偏向Mybatis了,违背了Hibernate的思想了。如果我们不想写sql,还是希望以对象形式更新数据。我们也可以写一个方法

    public void update(Class<T> clazz, K id, Map<String, Object> columns) {if (CollectionUtils.isEmpty(columns.keySet())) {throw new ParameterException(RetCode.HIBERNATE_COLUMNS_ARGS_LENGTH_ERROR);}StringBuilder hqlBuilder = new StringBuilder(" update " + clazz.getSimpleName() + " set ");columns.keySet().forEach(k -> hqlBuilder.append(k).append(" = :").append(k).append(", "));hqlBuilder.append(" updateTime = :updateTime ");hqlBuilder.append(" where id = :id ");commonDao.execute((ExecuteCallback<Object>) session -> {Query query = session.createQuery(hqlBuilder.toString());columns.keySet().forEach(k -> query.setParameter(k, columns.get(k)));query.setParameter("updateTime", new Date());query.setParameter("id", id);return query.executeUpdate();});}

那么我们在调用的时候

Map<String, Object> params = new HashMap<>();
params.put("status", "completed");
update(OrderInfo.class, orderInfo.getId(), params);

其实update方法内部还是在拼凑sql。

使用@version注解

使用@Version注解是Hibernate提供的一种乐观锁机制,用于解决并发更新时的数据覆盖问题。乐观锁是一种锁策略,它假设多个事务在同一时间对同一条记录进行更新的可能性较低,因此不采用在更新前加锁的方式(即悲观锁),而是在更新时检查版本号,如果发现版本冲突,则认为有其他事务已经更新了该记录,此时可以选择重新获取最新数据并再次尝试更新,或者抛出异常告知用户。当使用@Version注解标注在实体类的某个属性上时,Hibernate会在每次读取该记录时自动将版本号加1,并在更新时检查当前版本号与数据库中的版本号是否一致。如果版本号不一致,说明有其他事务已经更新了该记录,此时Hibernate会抛出OptimisticLockException异常,从而避免了数据覆盖的问题。

使用@Version注解的步骤如下:

  1. 选择版本号字段:选择一个合适的字段作为版本号字段,通常是一个数值类型或时间戳类型的字段。
  2. 添加注解:在实体类中的版本号字段上添加@Version注解。
  3. 处理异常:在业务层捕获OptimisticLockException异常,根据实际需求进行处理,例如提示用户重新操作或重试更新。

通过使用@Version注解,可以在不使用显式锁的情况下,依靠版本号机制来控制并发更新,从而避免数据覆盖的问题。但需要注意的是,乐观锁并不能保证数据的绝对一致性,因为在检查版本号和实际更新之间仍然存在短暂的时间窗口,极端情况下仍然可能发生并发更新的问题。因此,在使用乐观锁时需要仔细评估并发风险,并结合实际业务需求进行选择。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/805994.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大模型训练:如何解决GPU万卡互联挑战?

如何解决GPU万卡互联的挑战 近日&#xff0c;字节跳动携手北京大学研究团队发布重磅论文&#xff0c;揭示了一项革命性技术&#xff1a;将大型语言模型训练扩展至超10,000块GPU的生产系统。此系统不仅解决了万卡集群训练大模型时的效率和稳定性难题&#xff0c;更标志着人工智能…

用dbms_shared_pool.purge清除执行计划

1.Oracle 11g如何清除share pool中某条SQL的执行计划 以前在Oracle 10g数据库上,如果遇到绑定窥探导致执行计划慢的情况,想要清除某条SQL的执行计划,让它硬解析,找了很久都没有找到直接操作share pool的方法&#xff08;总不能alter system flush shared_pool&#xff09;,只能…

rocketmq和rabbitmq总是分不清?

1. 官方解答 摘自百度搜索&#xff1a; 2. 通俗易懂的回答

【Gem5】获取构建教程

gem5-tutorial-hpca-2023 1 介绍 1.1 Gem5是什么1.2 Gem5可以用来做什么1.3 获取并构建gem5 gem5-tutorial-hpca-2023 打开网址&#xff1a; github 创建教程代码空空间 “Code” -> “Codespaces” -> “Create Codespace on master” GitHub Codespaces 是一个由…

最坏情况为线性时间的第k大元素

在统计和数据分析中&#xff0c;我们经常会遇到求最大值、最小值、中位数、四分位数、Top K等类似需求&#xff0c;其实它们都属于顺序统计量&#xff0c;本文将对顺序统计量的定义和求解算法进行介绍&#xff0c;重点介绍如何在最差时间复杂度也是线性的情况下求解第k大元素。…

在Debian 12系统上安装Docker

Docker 在 Debian 12 上的安装 安装验证测试更多信息引言 在现代的开发环境中,容器技术发挥着至关重要的作用。Docker 提供了快速、可靠和易于使用的容器化解决方案,使开发人员和 DevOps 专业人士能够以轻松的方式将应用程序从一个环境部署到另一个环境。 Docker 的安装过程在…

实用运维工具(转载)

1、查看进程占用带宽情况-Nethogs Nethogs 是一个终端下的网络流量监控工具可以直观的显示每个进程占用的带宽。 下载&#xff1a;http://sourceforge.net/projects/nethogs/files/nethogs/0.8/nethogs-0.8.0.tar.gz/download [rootlocalhost ~]#yum -y install libpcap-deve…

C语言—每日选择题—Day68

第一题 1、运行以下C语言代码&#xff0c;输出的结果是&#xff08;&#xff09; #include <stdio.h> int main() {char *str[3] {"stra", "strb", "strc"};char *p str[0];int i 0;while(i < 3){printf("%s ",p);i;} retur…

在win10上虚拟一个LoongOS系统(类似虚拟机)作为开发环境

文章目录 1.安装1.1.下载这三个东西1.2.安装好qemu。1.3.创建一个启动脚本startup_mate.bat&#xff0c;然后把三部分东西放到一起1.4.然后双击startup.bat就可以启动了。 2.文件的传输2.1.使能虚拟机系统的ssh2.2.连接ssh 3.Qt相关安装Qt安装opencv 1.安装 注意&#xff0c;一…

ClickHouse--17--argMin() 和argMax()函数

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 argMin() 和argMax()函数业务场景使用案例1.准备表和数据&#xff1a;业务场景一&#xff1a;查看salary 最高和最小的user业务场景二&#xff1a;根据更新时间获取…

再也不怕面试官问 OOM了,一次生产环境 Metaspace OOM 排查流程实操!

问题背景 小奎公司的运维同时今天反映核心业务一个服务目前 CPU 的使用率、堆内存、非堆内存的使用率有点高。刚反映没有过多久该服务就直接 OOM 了&#xff0c;以下是生产监控平台监控信息。 CPU 使用率监控 堆内存和非堆内存使用率 OOM 产生的日志报错信息 问题分析 根…

Go第三方框架--ants协程池框架

1. 背景介绍 1.1 goroutine ants是站在巨人的肩膀上开发出来的&#xff0c;这个巨人是goroutine&#xff0c;这是连小学生都知道的事儿&#xff0c;那么为什么不继续使用goroutine(以下简称go协程)呢。这是个思考题&#xff0c;希望讲完本文大家可以有个答案。 go协程只涉及用…

Docker部署minio集群

1.基本定义 由于是非常轻量级的软件&#xff0c;所以架构上也没有这么复杂&#xff0c;他使用操作系统的文件系统作为存储介质&#xff0c;我们在向任意节点写数据的时候&#xff0c;minio会自动同步数据到另外的节点&#xff0c;而机制叫做erasure code&#xff08;纠删码&am…

linux内核驱动-在内核代码里添加设备结点

linux中&#xff0c;一切皆文件 我们在用户层用一些系统函数&#xff08;如&#xff1a;fopen等等&#xff09;时&#xff0c;会进入内核&#xff0c;内核会在字符注册了的设备号链表中查找。如果找到就运行我们写的设备文件的&#xff08;驱动&#xff09;函数 我们在前面已经…

RuoYi-Vue若依框架-vue前端给对象添加字段

处理两个字段的时候有需求都要显示在下拉框的同一行&#xff0c;这里有两种解决方案&#xff0c;一是后端在实体类添加一个对象&#xff0c;加注解数据库忽略处理&#xff0c;在接口处拼接并传给前端&#xff0c;二是在前端获取的数据数组内为每个对象都添加一个字段&#xff0…

cannal的使用

搭建MySQL 安装canal 1.新建文件夹logs, 新建文件canal.properties instance.properties docker.compose.yml instance.properties ################################################# ## mysql serverId , v1.0.26 will autoGen # canal.instance.mysql.slaveId0# enable g…

06 Php学习:字符串

PHP 中的字符串变量 在 PHP 中&#xff0c;字符串是一种常见的数据类型&#xff0c;用于存储文本数据。字符串变量可以包含字母、数字、符号等字符&#xff0c;并且可以进行各种操作和处理。以下是关于 PHP 中字符串变量的一些重要信息&#xff1a; 定义字符串变量&#xff1…

【SpringBoot3】Bean管理

1.Bean扫描 1.1传统Spring 标签&#xff1a;<context:component-scan base-package"com. example "/>注解&#xff1a;ComponentScan(basePackages "com.example") 1.2SpringBoot SpringBoot默认扫描启动类所在的包及其子包 2.Bean注册 如果要注…

SQL注入sqli_labs靶场第五、六题

第五题 根据报错信息&#xff0c;判断为单引号注入 没有发现回显点 方法&#xff1a;布尔盲注&#xff08;太耗时&#xff0c;不推荐使用&#xff09; 1&#xff09;猜解数据库名字&#xff1a;&#xff08;所有ASCII码值范围&#xff1a;0~127&#xff09; ?id1 and length…

TDengine too many open files

too many open files 是比较常见的报错&#xff0c;尤其使用TDengine 3.0 集群时&#xff0c;大概率会遇到。这个报错很简单&#xff0c;但要想顺利解决&#xff0c;却涉及到很多知识点。 目录 知识点&#xff1a;fs.nr_open知识点&#xff1a;file-max & fs.file-nr知识点…