Spring事物this调用当前类中的带事务方法导致事物失效
ApplicationContext获取代理后的当前类
调用当前类的事物方法时,如果使用this会导致获取的MainService这个对象本身,而非事物AOP后的MainService代理对象,所以一定要用ApplicationContext从IOC容器中获取。
MainService事务调用A和B方法
package com.example.transactiondemo.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationManager;
@Service
public class MainService {
@Autowired
private AService aService;
@Autowired
private BService bService;
@Autowired
private ApplicationContext applicationContext;
/**
* this.processAB(String data, String log);不会使用事物
*/
@Transactional(rollbackFor = Exception.class)
public void processMain(String data, String log) {
//这里一定不能使用this调用!!!this会导致获取的MainService这个对象,而非AOP后的MainService代理对象
//this.processAB(String data, String log);
//需要通过ApplicationContext从IOC容器中获取AOP代理后的对象
MainService mainService = applicationContext.getBean(MainService.class);
mainService.
}
/**
* 使用 ApplicationContext 获取代理对象或者直接使用DI注入的对象,保证事务生效
*/
@Transactional(rollbackFor = Exception.class)
public void processAB(String data, String log) {
System.out.println("Main类事务名称(代理调用):" + TransactionSynchronizationManager.getCurrentTransactionName());
// 通过IOC获取 A 和 B 的代理对象
//AService aService = applicationContext.getBean(AService.class);
//BService bService = applicationContext.getBean(BService.class);
//或者直接使用DI注入的对象
aService.saveOrUpdate(data);
bService.saveLog(log);
}
}
A类
package com.example.transactiondemo.service;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class AService {
//@Transactional(rollbackFor = Exception.class) save(insert或者update)不需要事物
public void saveOrUpdate(String data) {
System.out.println("A类事务名称:" + org.springframework.transaction.support.TransactionSynchronizationManager.getCurrentTransactionName());
System.out.println("A类保存或更新数据:" + data);
// 模拟抛出异常
if ("errorA".equals(data)) {
throw new RuntimeException("A类抛出异常,事务回滚!");
}
}
}
B类
package com.example.transactiondemo.service;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class BService {
//@Transactional(rollbackFor = Exception.class) 单个insert不用事物
public void saveLog(String log) {
System.out.println("B类事务名称:" + org.springframework.transaction.support.TransactionSynchronizationManager.getCurrentTransactionName());
System.out.println("B类插入日志:" + log);
// 模拟抛出异常
if ("errorB".equals(log)) {
throw new RuntimeException("B类抛出异常,事务回滚!");
}
}
}
Spring中事务测试代码
建立两张事务测试表
CREATE TABLE trancation_a (
id INT AUTO_INCREMENT PRIMARY KEY,
ta INT NOT NULL
);
CREATE TABLE trancation_b (
id INT AUTO_INCREMENT PRIMARY KEY,
tb INT NOT NULL
);
Spring代码
@Autowired
private JdbcTemplate jdbcTemplate;
/**
* 事务处理A和B
* 只需要在这个方法上添加即可,不需要在trancationA()和trancationB()上分别加事务
* 注意:如果调用processAB()方法是在当前类中,则也需要使用applicationContext对象获取当前类的代理对象
*/
@Transactional(rollbackFor = Exception.class)
public void processAB() throws Exception {
MqttLeakageFactory proxy = applicationContext.getBean(MqttLeakageFactory.class);
proxy.trancationA();
proxy.trancationB();
}
/**
* 操作A
* 单条表操作语句不用加事务
*/
public void trancationA() {
// Insert into table a
String insertA = "INSERT INTO trancation_a (ta) VALUES (11111)";
jdbcTemplate.update(insertA);
}
/**
* 操作B
* 单条表操作语句不用加事务
*/
public void trancationB() throws Exception {
// Insert into table b
String insertB = "INSERT INTO trancation_b (tb) VALUES (222222)";
jdbcTemplate.update(insertB);
throw new Exception("事务B异常");
}
如果这篇文章对你有用,可以关注本人微信公众号获取更多ヽ(^ω^)ノ ~

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
2019-12-25 宝塔安装
2019-12-25 js判断浏览器版本
2019-12-25 JS打开url的几种方法
2018-12-25 计算机存储单位及网络传输单位