首页 > 解决方案 > 在 Java Spring 中调试事务注解

问题描述

更新现有的一段代码,如下所示:

@Override
@Transactional
public void update(SomeObject someObj) throws BusinessServiceException {
    ...
    someObjectRepository1.update(someObj);
    someObjectRepository2.create(someObj);

    //New code below:
    someObjectRelatedService.doStuff(someObj);  // <--new code
    //Throws error, object does not exist in someObjectRepository2
}

这里的问题是someObjectRelatedService.doStuff需要 someObjectRepository2 的最新和最新版本 - 但是事务注释阻止了这种情况的发生,它在方法完全运行后更新存储库。我能够通过使用调试器并在两者之间运行数据库调用来进行验证。

处理这种情况的最佳方法是什么?是否仅在事务方法之外提取 someObjectRelatedService 调用?

标签: javaspringannotations

解决方案


本质上,您需要移动事务的边界。虽然手动刷新事务是一种选择,但我不建议这样做。

如果语义SomeObjectRepository2#create(...)允许,最简单的解决方法是用@Transactional(isolation = Propagation.REQUIRES_NEW).

如果这不可能,我建议进行以下小的重新设计。首先,我们用一个方法创建一个新类,它应该执行与所需数据相关的代码:

@Component
public class NewClass {
    final SomeObjectRepository2 someObjectRepository2;

    @Autowired
    public NewClass(final SomeObjectRepository2 someObjectRepository2) {
        this.someObjectRepository2 = someObjectRepository2;
    }

    @Transactional(isolation = Propagation.REQUIRES_NEW) // enforces new transaction
    public WhateverNeedsToBereturned newMethod(WhateverType someObject) {
        return someObjectRepository2.create(someObj);
    }
}

然后我们重写现有代码以使用新类:

@Override
@Transactional
public void update(SomeObject someObj) throws BusinessServiceException {
    ...
    someObjectRepository1.update(someObj);
    newClassInstance.newMethod(someObj);

    //New code below:
    someObjectRelatedService.doStuff(someObj); 
    //Throws error, object does not exist in someObjectRepository2
}

请注意,您必须创建一个新类才能使其正常工作。通过this-reference 调用的方法不会被代理,因此@Transactional注释不会生效。

进一步注意,newClassInstance出于同样的原因,必须通过 DI 容器注入。


推荐阅读