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

news2025/3/1 4:52:55

前言

今天现网有个订单卡单了,经过排查发现没有任何异常日志,根据日志定位发现本应该更新的一个状态,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日志

从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.coloradmin.cn/o/1584982.html

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

相关文章

Qt6 multimedia开发一个摄像头录像机

Qt 6 附加模块multimedia可用于多媒体的开发&#xff0c;今天使用它可以快速开发一个摄像头录像机。 毕业季用作本科毕业设计软件应该可以的。 支持的功能 无边框窗口&#xff0c;并且支持拖拽&#xff0c;调整窗口大小切换摄像头配置摄像头原格式、分辨率、帧率、画面质量、…

opencv图像处理技术(形态学操作)

形态学&#xff08;Morphology&#xff09;是数学中研究形状、结构和变换的分支&#xff0c;而在图像处理中&#xff0c;形态学主要用于描述和分析图像中的形状和结构。形态学操作通常涉及基本的集合运算&#xff0c;如腐蚀、膨胀、开运算、闭运算等&#xff0c;以及与结构元素…

云原生__K8S

createrepo --update /var/localrepo/# 禁用 firewall 和 swap [rootmaster ~]# sed /swap/d -i /etc/fstab [rootmaster ~]# swapoff -a [rootmaster ~]# dnf remove -y firewalld-*[rootmaster ~]# vim /etc/hosts 192.168.1.30 harbor 192.168.1.50 master 192.168.1.…

互联网大厂ssp面经之路:计算机网络part1

1. 计算机网络的组成部分有哪些&#xff1f; a. 硬件设备&#xff1a;计算机网络由各种硬件设备组成&#xff0c;包括计算机、服务器、路由器、交换机、网卡等。这些设备通过物理连接&#xff08;如网线、光纤&#xff09;相互连接。 b. 协议&#xff1a;计算机网络中的通信需…

一个巧用委托解决的问题(C#)

个人觉得是委托应用的一个很好的例子&#xff0c;故做一下分享&#xff0c;希望能帮助到您&#xff0c;内容比较简单&#xff0c;大佬可以跳过。我是做桌面医疗软件开发的&#xff0c;前段时间在做一个需求。在签发检验项目医嘱时&#xff0c;调用第三方接口&#xff0c;然后带…

什么是生成式AI?有哪些特征类型

生成式AI是人类一种人工智能技术&#xff0c;可以生成各种类型的内容&#xff0c;包括文本、图像、音频和合成数据。那么什么是人工智能&#xff1f;人工智能和机器学习之间的区别是什么&#xff1f;有哪些技术特征&#xff1f; 人工智能是一门学科&#xff0c;是计算机科学的一…

漫途水产养殖水质智能监测方案,科技助力养殖业高效生产!

随着水产养殖业的蓬勃发展&#xff0c;水质和饲料等多重因素逐渐成为影响其持续健康发展的关键因素。由于传统养殖模式因监控和调节手段不足&#xff0c;往往造成养殖环境的恶化。需要通过智能化养殖&#xff0c;调控养殖环境&#xff0c;实现养殖的精细化管理模式&#xff0c;…

Python爬虫网络实践:去哪儿旅游数据爬取指南

Python爬虫网络实践&#xff1a;去哪儿旅游数据爬取指南 在这个博客中&#xff0c;我们将探索如何使用 Python 来进行网络数据抓取&#xff0c;并以抓取旅游数据为例进行演示。我们将通过一个简单的示例来说明如何利用 Python 中的常用库进行网页抓取&#xff0c;从而获取旅游…

Go语言开发工具Vscode配置

Go语言开发工具Vscode配置方法分享&#xff1a; 1.下载安装vscode https://code.visualstudio.com/ 2.汉化vscode 3.vscode中安装Go语言插件 源自&#xff1a;大地老师Golang语言beego入门实战视频教程下载地址

rsync 远程同步----------安全高效的异地备份方案

目录 一、rsync介绍 rsync和cp的区别 rsync和scp的区别 二、rsync同步方式 rsync备份的方式 三、配置rsync源服务器 ①本地复制 ②下行同步 ③上行同步 四、常用Rsync命令 五、配置源的两种表达方法 六、部署rsync下行同步 ①环境准备 ②配置rsync源服务器------…

[大模型]Qwen1.5-7B-Chat 接入 LangChain 搭建知识库助手

Qwen1.5-7B-Chat 接入 LangChain 搭建知识库助手 环境准备 在 autodl 平台中租赁一个 3090 等 24G 显存的显卡机器&#xff0c;如下图所示镜像选择 PyTorch–>2.0.0–>3.8(ubuntu20.04)–>11.8 接下来打开刚刚租用服务器的 JupyterLab&#xff0c;并且打开其中的终端…

String类(1)

❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; hellohello~&#xff0c;大家好&#x1f495;&#x1f495;&#xff0c;这里是E绵绵呀✋✋ &#xff0c;如果觉得这篇文章还不错的话还请点赞❤️❤️收藏&#x1f49e; &#x1f49e; 关注&#x1f4a5;&a…

45-基于Kubernetes的云原生架构设计

云原生简介 云原生包含的概念很多&#xff0c;对于一个应用开发者来说&#xff0c;主要关注点是如何开发应用&#xff0c;以及如何部署应用。会主要介绍应用层的云原生架构设计和系统资源层的云原生架构设计。 CNCF&#xff08;云原生计算基金会&#xff09;简介 CNCF&#x…

竞品数据的监测范围

常规的数据监测一般指的是价格监测&#xff0c;品牌对线上产品链接中的页面价、到手价进行监测&#xff0c;同时也可监测标题变化、销量变化、库存变化、优惠信息变化等&#xff0c;对于对够执行数据监测的系统来说&#xff0c;不管哪个品牌的数据都可做到以上维度的监测&#…

SOCKS代理概述

在网络技术的广阔领域中&#x1f310;&#xff0c;SOCKS代理是一个核心组件&#xff0c;它在提升在线隐私保护&#x1f6e1;️、实现匿名通信&#x1f3ad;以及突破网络访问限制&#x1f6ab;方面发挥着至关重要的作用。本文旨在深入探讨SOCKS代理的基础&#xff0c;包括其定义…

阿里云云效CI/CD配置

1.NODEJS项目流水线配置(vue举例) nodejs构建配置 官方教程 注意:下图的dist是vue项目打包目录名称,根据实际名称配置 # input your command here cnpm cache clean --force cnpm install cnpm run build 主机部署配置 rm -rf /home/vipcardmall/frontend/ mkdir -p /home/…

SV-7042V 40W网络有源音柱 智慧灯杆广播音柱

SV-7042V 40W网络有源音柱 一、描述 SV-7042V是深圳锐科达电子有限公司的一款壁挂式网络有源音柱&#xff0c;具有10/100M以太网接口&#xff0c;可将网络音源通过自带的功放和喇叭输出播放&#xff0c;其采用防水设计&#xff0c;功率40W。 SV-7042V作为网络广播播放系统的终…

Go——网络编程

一. 互联网协议介绍 网络基础——网络传输基本流程_网络传输过程-CSDN博客 应用层HTTP协议-CSDN博客 传输层UDP/TCP协议_udp报文提供的确认号用于接收方跟发送方确认-CSDN博客 网络层IP协议-CSDN博客 链路层以太网详解_以太网数据链路层-CSDN博客 二. Socket编程 Socket是…

智能运维场景 | 科技风险预警,能实现到什么程度?

[ 原作者&#xff1a;擎创夏洛克&#xff0c;本文略做了节选和改编 ] 每次一说到“风险预警”&#xff0c;就会有客户问我们能做怎样的风险预警。实际上在智能运维厂商来说&#xff0c;此风险非彼风险&#xff0c;不是能做银行的业务上的风险预警&#xff08;比如贷款风险等&a…

Day 22 235. 二叉搜索树的最近公共祖先 701.二叉搜索树中的插入操作 450.删除二叉搜索树中的节点

二叉搜索树的最近公共祖先 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个结点 p、q&#xff0c;最近公共祖先表示为一个结点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#…