spring事务REQUIRES_NEW失效

问题描述: 在service某方法中执行了a方法和b方法,a上面加了默认事务传播行为,b传播行为是REQUIRES_NEW,但是b失败导致了a事务的回滚,就很奇怪。

原因:jdk动态代理中执行嵌套方法不会走代理,而是把嵌套的方法直接移动到原方法进行执行了。
下面进行验证:

public class ObjectProxy implements InvocationHandler {
    private Object target;

    public ObjectProxy(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("==========6666===========");
        return method.invoke(target,args);
    }


    public Object getProxy() {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                target.getClass().getInterfaces(),this);
    }

}
class Te{
    public static void main(String[] args) {
        SkuInfoServiceImpl skuInfoServiceImpl = new SkuInfoServiceImpl();
        ObjectProxy objectProxy = new ObjectProxy(skuInfoServiceImpl);
        SkuInfoService skuInfoService = (SkuInfoService) objectProxy.getProxy();
        skuInfoService.test1();
//        skuInfoService.test2();

    }
}
public interface SkuInfoService extends IService<SkuInfoEntity> {
    void test1();
    void test2();
}
@Service("skuInfoService")
public class SkuInfoServiceImpl implements SkuInfoService {
    @Override
    public void test1() {
        System.out.println("test1");
        test2();
    }

    @Override
    public void test2() {
        System.out.println("test2");
    }

比如执行上面代码,代理对象执行test1方法,test1中包含test2,test2方法并不会走代理对象。

 执行结果,只会走一次代理。
 
==========6666===========
test1
test2

所以事务那边就说得通了,

解决办法:
强制使用Aop的cglib代理。启动类添加注解

@EnableAspectJAutoProxy(exposeProxy = true)

并且执行的时候,要分别从AopContext中获取当前代理对象xxxService,然后分别调用xxxService.a()和xxxService.b();

另外注意,b方法中的异常一定要在外面进行try catch,不然b方法的异常会一直往外抛导致所有事务均异常全部回滚,还误以为代理失败。

### Spring 中 `PROPAGATION_REQUIRES_NEW` 传播行为下内部事务回滚原因 当配置了 `PROPAGATION_REQUIRES_NEW` 的情况下,每次调用带有此属性的方法时都会启动一个新的独立事务。即使外部存在另一个事务上下文,新创建的事务也会完全独立运行并提交或回滚[^3]。 然而,在某些场景中发现即便如此指定,内部事务依旧可能出现回滚现象: 1. **异常抛出**:如果在标记为 `PROPAGATION_REQUIRES_NEW` 的方法体内发生未捕获到的受检或者非受检异常,则会触发该事务自动设置为只读状态(即调用了 `isRollbackOnly()`),从而导致最终无法成功提交而且回滚整个操作[^1]。 2. **嵌套保存点机制失效**:虽然理论上讲两个不同级别的事务应该互不影响;但是由于数据库连接共享等因素影响,在特定条件下可能会造成子级事务的状态改变反过来作用于父级事务上。特别是对于一些不支持真正的分布式多层事务管理的数据源来说更为明显[^2]。 3. **平台特性差异**:不同的持久化框架以及底层JDBC驱动程序实现细节上的差别也可能引起意想不到的行为表现形式。例如某些版本可能存在Bug或者是设计之初就没有很好地遵循标准规范来处理这种复杂的并发控制情况[^4]。 为了确保能够按照预期工作,建议仔细审查代码逻辑中的错误捕捉部分,并确认所使用的基础设施组件是否具备良好的兼容性稳定性。 ```java // 示例代码展示如何正确使用 PROPAGATION_REQUIRES_NEW 并处理可能发生的异常 @Transactional(propagation = Propagation.REQUIRES_NEW) public void performOperationWithinNewTransaction() { try { // 执行业务逻辑... } catch (Exception e) { log.error("An error occurred during operation within new transaction", e); throw e; } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值