事物以及事物隔离性的代码详解

2024-08-22 20:58
文章标签 代码 详解 隔离 事物

本文主要是介绍事物以及事物隔离性的代码详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

不多bb了,直接上代码和注释,看不懂的找博主

数据库初始状态

   //数据库中 id = 1 name = 0000 balance = 2222//数据库中 id = 2 name = aaaa balance = null//other id = 1 name = AAAA//other id = 2 name = BBBB

总结:

1、事物开启的时间

如果service中即使一开始就表明了执行事物,但是事物开启的时间也要算在执行数据库语句的时候开开始

举例:一开始表1中name为0000,打上断点,先进入service,不操作数据库。这个时候手动修改数据库中的name为1111,再执行查询语句,我们会发现取到了那么为1111的值,而不是0000(安装可重复读取的思想解决)(不论是可重复读REPEATABLE_READ还是不可重复读READ_COMMITTED

如果是sql(注意一定是sql)更新操作,我们在当前事物中进行了更新操作,其他事物更新相同id的数据,则其他事物不能修改,因为更新操作会将这条数据锁住(排它锁),其他事物不能更新执这条id的数据(可以使用select普通查看,hibernate save方法更新不会马上执行sql语句,它会等到事物最后全部执行完成、或者这条数据的记录直到本事物中对它进行数据库操作的时候才会执行sql语句,所以hibernate相关save更新按照代码情况进行锁住锁住,影响到别的事物对它进行修改)


->(包括,新开启了一个独立事物对它进行修改也不能完成),但是对于其他的id是可以任意修改的的,除非等当前事物执行完成或者当前事物回滚(总之就是当前事物结束)


### 2、可重复读取`REPEATABLE_READ`

事物开始执行的时候,相当于我们将数据库中进行了一个拍照,不论其他事物修改了其他或者本表任何表的任何数据,我们通过find看到的数据都是拍照的数据,也就是说即使其他事物对我们拿到的数据进行了更新,或者添加了新的数据,我们还是看不到。我们只能拿到照片中的数据。


3、不可重复读READ_COMMITTED 一般情况下建议使用

1、只要不是我们从当前事物中取到的数据,其他事物修改了其他或者本表任何表的任何数据,我们查询的话,就是显示最新的数据


2、如果我们正在执行的事物取到了数据,即使别的事物修改成什么样子,我们再查询的话,还是一样的(不管是hibernate查询还是sql查询),相当于只给我们当前查询过的数据拍了照片(其实这个是我实际项目中得到的结果,但是关于网上给出的其他事物修改提交了,这里再次执行,应该是得到最新的数据)

4、update操作和重新赋值给另一个对象实体中内容变化不变化

1、update 原生 sql语句不会更新当前实体对象,
2、如果是同一个事物中,如果是一个根据id 进行更新,并且返回了结果 ,hibernate的操作会即使重新new一个对象出来也会对原理的对象 进行更新
3、如果是中间独立事物进行了修改,返回了其他对象,不会更新当前实体对象。

DemoEntity demoEntity =  demoEntityRepository.findOne(id);isolationService.updateName(id,"zhang123456" ); @Modifying@Query("UPDATE  DemoEntity  d set d.name = ?2 where d.id = ?1")int updateName(Long id ,String name);//即使重新赋值了新对象one,上面的demoEntity 也会跟着变化,一个事物中的数据,具有连贯性,update语句,则是返回了一个当前行。DemoEntity one = isolationService.transRequirs(1L,"transRequirsOne");

下面主要是可重复读取的数据package com.hlj.springboot.dome.common.moudle.service;import com.hlj.springboot.dome.common.entity.DemoEntity;
import com.hlj.springboot.dome.common.entity.OtherEntity;
import com.hlj.springboot.dome.common.entity.repository.DemoEntityRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;/*** 作者 :HealerJean* 日期 :2019/1/23  下午8:02.* 类描述:*/
@Service
public class IsolationStartService {@Resourceprivate DemoEntityRepository demoEntityRepository ;@Resourceprivate IsolationService isolationService ;@Transactional(isolation = Isolation.READ_COMMITTED ,propagation = Propagation.REQUIRED,rollbackFor = Exception.class)public DemoEntity startTransactional(Long id) {//数据库中 id = 1 name = 0000 balance = 2222//数据库中 id = 2 name = aaaa balance = null//other id = 1 name = AAAA//other id = 2 name = BBBB//这个时候修改id为1的name为1111,以下查询还没有开启,表明我们的事物目前为止其实还没有开启,因为没有涉及到数据库的操作,有了数据库操作,才会真正开启事物DemoEntity demoEntity =  demoEntityRepository.findOne(id);demoEntity.setName("startTransactional"); //还没有保存到数据库中,因为事物还没有提交,方法运行结束才会提现目前开启的这个事物,除非中间出现独立事物System.out.println(demoEntity);     //DemoEntity(id=1, name=startTransactional, balance=2222)//开始独立事物直接保存数据,直接在数据库中有显示DemoEntity transRequirsNew =   isolationService.transRequirsNew(id,"transRequirsNew");System.out.println(transRequirsNew); //DemoEntity(id=1, name=transRequirsNew, balance=2222)//解释:即使独立事物修改过,我们这里还是不会变,还是本事物中的数据(因为是两个事物,具有隔离性)System.out.println(demoEntity);  //DemoEntity(id=1, name=startTransactional, balance=2222)//当前事物下保存数据,上面的额startTransactional 事物还没有提交,所以和一开始的状态是一致的demoEntity = isolationService.transRequirs(id,"transRequirs");System.out.println(demoEntity) ; //DemoEntity(id=1, name=transRequirs, balance=2222)// 目前,直接看数据库中,name应该能是transRequirsNew, 手动修改数据库中的 name为 3333//读取已经提交的数据,这里没有开启独立事物,所以即使配置了,读已提交也不会生效,因为再我们这个方法一开始的时候,就已经确定了隔离性质demoEntity = isolationService.isoLationReadCommitedFind(id);System.out.println(demoEntity); // DemoEntity(id=1, name=transRequirs, balance=2222)// 可重复读 这个时候我们修改 2中的数据为 bbbb,会发现这个时候查询的时候,下面还为aaa ,// READ_COMMITTED 可重复读取:修改了之后,我们查询到的数据库是bbbb,说明READ_COMMITTED 生效了DemoEntity two = isolationService.transRequirsFind(2L);System.out.println(two) ;//可重复读          DemoEntity(id=2, name=aaaa, balance=null)//READ_COMMITTED   DemoEntity(id=2, name=bbbb, balance=null)//下面一起修改了即使换一个变量名字,demoEntity的变量还是会跟着变的DemoEntity one = isolationService.transRequirs(1L,"transRequirsOne");System.out.println(one) ; //DemoEntity(id=1, name=transRequirsOne, balance=2222)System.out.println(demoEntity) ; //DemoEntity(id=1, name=transRequirsOne, balance=2222)//可重复读 这个时候直接修改 这张表中的数据为CCCC,我们会发现本事物中查询的还是之前的结果AAAA,说明本事物开启之后,就会对数据库中的数据进行锁定(相当于是拍了张照片)//READ_COMMITTED 这个时候直接修改数据库 这张表中的数据为CCCC, 这里查询得到的是CCCC,说明不可重复读生效了OtherEntity otherEntity = isolationService.findOther(1L);System.out.println(otherEntity);//可重复读 OtherEntity(id=1, name=AAAA)//READ_COMMITTED OtherEntity(id=1, name=CCC)//可重复读 这个时候直接修改 这张表中的数据为DDDD,我们会发现本事物中查询的还是之前的结果BBBB//READ_COMMITTED 这个时候直接修改数据库 这张表中的数据为CCCC, 这里查询得到的是CCCC,说明不可重复读生效了OtherEntity otherEntityTwo = isolationService.findOther(2L);System.out.println(otherEntityTwo);//可重复读 OtherEntity(id=2, name=BBBB)//READ_COMMITTED OtherEntity(id=2, name=DDDD)//指定id更新不会影响demoEntity 现在的数据isolationService.updateName(id,"zhang123456" );System.out.println(demoEntity); //DemoEntity(id=1, name=transRequirsOne, balance=2222)System.out.println(transRequirsNew);//DemoEntity(id=1, name=transRequirsNew, balance=2222)return demoEntity;//上面两种的最终数据库中就 都变成了// id =1 name= zhang123456  balance = 2222// id =2 name= bbb balance = nulll//other表 id= 1 name =CCCC//id = 2 name =DDDD}}

1、接口

package com.hlj.springboot.dome.common.moudle.service;import com.hlj.springboot.dome.common.entity.DemoEntity;
import com.hlj.springboot.dome.common.entity.OtherEntity;/*** 作者 :HealerJean* 日期 :2019/1/23  下午7:34.* 类描述:*/
public interface IsolationService {/*** 方法中的事物为入口方法的事物* @param id* @return*/DemoEntity  transRequirs(Long id,String name);DemoEntity  transRequirsFind(Long id);/*** 开启一个事物* @param id* @return*/DemoEntity  transRequirsNew (Long id,String name);/*** 事物隔离级别为 读已提交()* @param id* @return*/DemoEntity   isoLationReadCommitedFind(Long id) ;int updateName(Long id,String name);OtherEntity findOther(Long id);}

3、接口实现类

package com.hlj.springboot.dome.common.moudle.service.impl;import com.hlj.springboot.dome.common.entity.DemoEntity;
import com.hlj.springboot.dome.common.entity.OtherEntity;
import com.hlj.springboot.dome.common.entity.repository.DemoEntityRepository;
import com.hlj.springboot.dome.common.entity.repository.OtherEntityRepository;
import com.hlj.springboot.dome.common.moudle.service.IsolationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;/*** 作者 :HealerJean* 日期 :2019/1/23  下午7:35.* 类描述:*/
@Service
@Slf4j
public class IsolationServiceImpl  implements IsolationService {@Resourceprivate DemoEntityRepository demoEntityRepository ;@Resourceprivate OtherEntityRepository otherEntityRepository ;@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)@Overridepublic DemoEntity transRequirs(Long id,String name) {DemoEntity demoEntity =  demoEntityRepository.findOne(id);demoEntity.setName(name);return demoEntityRepository.save(demoEntity);}@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)@Overridepublic DemoEntity transRequirsFind(Long id) {return demoEntityRepository.findOne(id);}@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)@Overridepublic DemoEntity transRequirsNew(Long id,String name) {DemoEntity demoEntity =  demoEntityRepository.findOne(id);demoEntity.setName(name);return demoEntityRepository.save(demoEntity);}@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED,rollbackFor = Exception.class)@Overridepublic DemoEntity isoLationReadCommitedFind(Long id) {return demoEntityRepository.findOne(id);}@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)@Overridepublic int updateName(Long id, String name) {return demoEntityRepository.updateName(id,name);}@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)@Overridepublic OtherEntity findOther(Long id) {return otherEntityRepository.findOne(id);}
}





感兴趣的,欢迎添加博主微信,

哈,博主很乐意和各路好友交流,如果满意,请打赏博主任意金额,感兴趣的在微信转账的时候,备注您的微信或者其他联系方式。添加博主微信哦。


请下方留言吧。可与博主自由讨论哦

微信微信公众号支付宝
微信微信公众号支付宝

这篇关于事物以及事物隔离性的代码详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1097374

相关文章

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

K8S(Kubernetes)开源的容器编排平台安装步骤详解

K8S(Kubernetes)是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。以下是K8S容器编排平台的安装步骤、使用方式及特点的概述: 安装步骤: 安装Docker:K8S需要基于Docker来运行容器化应用程序。首先要在所有节点上安装Docker引擎。 安装Kubernetes Master:在集群中选择一台主机作为Master节点,安装K8S的控制平面组件,如AP

代码随想录冲冲冲 Day39 动态规划Part7

198. 打家劫舍 dp数组的意义是在第i位的时候偷的最大钱数是多少 如果nums的size为0 总价值当然就是0 如果nums的size为1 总价值是nums[0] 遍历顺序就是从小到大遍历 之后是递推公式 对于dp[i]的最大价值来说有两种可能 1.偷第i个 那么最大价值就是dp[i-2]+nums[i] 2.不偷第i个 那么价值就是dp[i-1] 之后取这两个的最大值就是d

pip-tools:打造可重复、可控的 Python 开发环境,解决依赖关系,让代码更稳定

在 Python 开发中,管理依赖关系是一项繁琐且容易出错的任务。手动更新依赖版本、处理冲突、确保一致性等等,都可能让开发者感到头疼。而 pip-tools 为开发者提供了一套稳定可靠的解决方案。 什么是 pip-tools? pip-tools 是一组命令行工具,旨在简化 Python 依赖关系的管理,确保项目环境的稳定性和可重复性。它主要包含两个核心工具:pip-compile 和 pip

D4代码AC集

贪心问题解决的步骤: (局部贪心能导致全局贪心)    1.确定贪心策略    2.验证贪心策略是否正确 排队接水 #include<bits/stdc++.h>using namespace std;int main(){int w,n,a[32000];cin>>w>>n;for(int i=1;i<=n;i++){cin>>a[i];}sort(a+1,a+n+1);int i=1