当前位置:网站首页>多线程保证单个线程开启事务并生效的方案
多线程保证单个线程开启事务并生效的方案
2022-07-30 09:26:00 【傻鱼爱编程】
我们开发的时候常常会遇到多线程事务的问题。以为添加了@Transactional注解就行了,其实你加了注解之后会发现事务失效。原因:数据库连接spring是放在threadLocal里面,多线程场景下,拿到的数据库连接是不一样的,即是属于不同事务。
Spring支持编程式事务和声明式事务,Spring提供的最原始的事务管理方式是基于TransactionDefinition、PlatformTransactionManager、TransactionStatus 编程式事务。
TransactionTemplate的事务管理是使用模板方法设计模式对原始事务管理方式的封装,因此我们也可以用TransactionTemplate管理事务。
今天我们就来谈下单个线程开启事务的方案:
1. 直接把线程方法单独提出,添加@Transactional注解
// 开启多线程的方法
public void testTransactional() throws ExecutionException, InterruptedException {
int inter = 3;
ExecutorService executorService = Executors.newFixedThreadPool(inter);
ThreadPoolExecutor poolExecutor = (ThreadPoolExecutor) executorService;
FutureTask[] integerFuture = new FutureTask[inter];
for (int i = 0; i < inter; i++) {
int finalI = i + 1;
integerFuture[i] = new FutureTask<>(() -> {
testTransactionalServiceZi.testTransactionalZi(finalI, "计算" + finalI);
System.out.println("多线程运行了---" + finalI);
return "业务执行成功";
});
poolExecutor.execute(integerFuture[i]);
}
for (int i = 0; i < inter; i++) {
System.out.println("integerFuture返回结果 = " + i + "==" + integerFuture[i].get());
}
}
// 单个线程调用,添加注解
@Transactional
public void testTransactionalZi(int num, String str) {
// 修改数据===1===
AdCourse adCourse = new AdCourse();
adCourse.setId(num);
adCourse.setName(str);
int i = adCourseMapper.updateById(adCourse);
// 修改数据===2===
adCourse.setId(num + 3);
adCourse.setName(str + 0);
int result = adCourseMapper.updateById(adCourse);
// 手动制造异常(事务会生效)
result = 1/0;
}2. 用TransactionTemplate管理事务
通过对源码的解读,TransactionTemplate封装的是PlatformTransactionManager。我们自己手写PlatformTransactionManager管理事务比较麻烦,所以通过TransactionTemplate来进行展示代码,如下:
@Service
public class TestTransactionalServiceImpl implements TestTransactionalService {
@Autowired
private TestTransactionalServiceZi testTransactionalServiceZi;
// 使用Template控制事务
@Autowired
private TransactionTemplate template;
public void testTransactional() throws ExecutionException, InterruptedException {
int inter = 3;
ExecutorService executorService = Executors.newFixedThreadPool(inter);
ThreadPoolExecutor poolExecutor = (ThreadPoolExecutor) executorService;
FutureTask[] integerFuture = new FutureTask[inter];
for (int i = 0; i < inter; i++) {
int finalI = i + 1;
integerFuture[i] = new FutureTask<>(() -> {
return template.execute(new TransactionCallback<String>() {
@Override
public String doInTransaction(TransactionStatus transactionStatus) {
testTransactionalServiceZi.testTransactionalZi(finalI, "计算666" + finalI);
System.out.println("多线程运行了---" + finalI);
return "业务执行成功";
}
});
});
poolExecutor.execute(integerFuture[i]);
}
for (int i = 0; i < inter; i++) {
System.out.println("integerFuture返回结果 = " + i + "==" + integerFuture[i].get());
}
}
}
// 需要调用的方法
public void testTransactionalZi(int num, String str) {
// 修改数据===1===
AdCourse adCourse = new AdCourse();
adCourse.setId(num);
adCourse.setName(str);
int i = adCourseMapper.updateById(adCourse);
// 修改数据===2===
adCourse.setId(num + 3);
adCourse.setName(str + 0);
int result = adCourseMapper.updateById(adCourse);
// 手动制造异常(事务会生效)
result = 1/(num-1);
}打印结果:第一个线程没有执行成功,出现了异常,数据也没有改变。

总结:以上两种方法可以保证多线程中单个线程事务的问题
边栏推荐
- Version management of public Jar packages
- leetcode 剑指 Offer 57. 和为s的两个数字
- 图像分析:投影曲线的波峰查找
- 转行软件测试,报培训班3个月出来就是高薪工作,靠谱吗?
- Day113.尚医通:微信登录二维码、登录回调接口
- C#中Config文件中,密码的 特殊符号的书写方法。
- 2022/07/29 Study Notes (day19) Exception Handling
- Four ways the Metaverse is changing the way humans work
- 函数式接口&Lambda表达式——简单应用笔记
- leetcode 剑指 Offer 25. 合并两个排序的链表
猜你喜欢

Baidu promotion assistant encounters duplicate keywords, verification errors, how to delete redundant ones with one click

(Text) Frameless button settings

Unreal Engine Graphic Notes: could not be compiled. Try rebuilding from source manually. Problem solving

MySQL Explain 使用及参数详解

leetcode 剑指 Offer 15. 二进制中1的个数

(文字)无框按钮设置

20220728 Use the bluetooth on the computer and the bluetooth module HC-05 of Huicheng Technology to pair the bluetooth serial port transmission

02-课程发布

XP电源维修fleXPower电源X7-2J2J2P-120018系列详解

Devops和低代码的故事:螳螂捕蝉,黄雀在后
随机推荐
通过构建一个顺序表——教你计算时间复杂度和空间复杂度(含递归)
Re16:读论文 ILDC for CJPE: Indian Legal Documents Corpus for Court Judgment Prediction and Explanation
宝塔搭建DM企业建站系统源码实测
leetcode 剑指 Offer 12. 矩阵中的路径
Baidu promotion assistant encounters duplicate keywords, verification errors, how to delete redundant ones with one click
els 方块向左移动
Shell系统学习之函数
初识Apifox——如何使用Apifox做一个简单的接口测试
leetcode 剑指 Offer 52. 两个链表的第一个公共节点
mysql安装教程【安装版】
自动化测试selenium(一)
An article to understand service governance in distributed development
Use the R language to read the csv file into a data frame, and then view the properties of each column.
Shell系统学习之数组
2022 Hangzhou Electric Multi-School 2nd Game
【无标题】
C# 之 $ – 字符串内插
ThreadLocal内存泄漏是伪命题?
Day113.尚医通:微信登录二维码、登录回调接口
PyQt5快速开发与实战 7.4 事件处理机制入门 and 7.5 窗口数据传递