当前位置:网站首页>多线程保证单个线程开启事务并生效的方案
多线程保证单个线程开启事务并生效的方案
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);
}打印结果:第一个线程没有执行成功,出现了异常,数据也没有改变。

总结:以上两种方法可以保证多线程中单个线程事务的问题
边栏推荐
- Domino服务器SSL证书安装指南
- Re18: Read the paper GCI Everything Has a Cause: Leveraging Causal Inference in Legal Text Analysis
- 百度推广助手遇到重复关键字,验证错误,怎么一键删除多余的
- leetcode 剑指 Offer 12. 矩阵中的路径
- conda 导出/导出配置好的虚拟环境
- 2022/07/29 Study Notes (day19) Exception Handling
- echart图表清空上一次数据
- MySQL中使用IN 不会走索引分析以及解决办法
- 宝塔搭建DM企业建站系统源码实测
- PyQt5快速开发与实战 7.4 事件处理机制入门 and 7.5 窗口数据传递
猜你喜欢

69. Sqrt(x)x 的平方根

国外资源加速下载器,代码全部开源

Re16:读论文 ILDC for CJPE: Indian Legal Documents Corpus for Court Judgment Prediction and Explanation

Unified exception handling causes ResponseBodyAdvice to fail

Using IN in MySQL will not go through index analysis and solutions

Matplotlib--绘图标记

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

(***重点***)Flink常见内存问题及调优指南(一)

Jetpack Compose 从入门到入门(八)

Unreal Engine Graphic Notes: could not be compiled. Try rebuilding from source manually. Problem solving
随机推荐
Re18:读论文 GCI Everything Has a Cause: Leveraging Causal Inference in Legal Text Analysis
Kotlin value class - value class
你真的懂Redis的5种基本数据结构吗?
编译报错: undefined reference to `google::FlagRegisterer::FlagRegisterer解决方法
606. 根据二叉树创建字符串(视频讲解!!!)
MySQL数据库题库
leetcode 剑指 Offer 47. 礼物的最大价值
C语言顺序表基本操作
leetcode 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
els 方块停在方块上。
0729放假自习
2022 Hangzhou Electric Multi-School 2nd Game
使用 Neuron 接入 Modbus TCP 及 Modbus RTU 协议设备
idea2021+Activiti【最完整笔记一(基础使用)】
Test automation selenium (a)
XP电源维修fleXPower电源X7-2J2J2P-120018系列详解
一文理解分布式开发中的服务治理
Shell系统学习之数组
An article to understand service governance in distributed development
快解析结合泛微OA