在 Java Spring 中调试事务注释
debugging Transactional annotation in 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 - 但 t运行sactional 注释阻止了这种情况的发生,它在方法完全 运行 之后更新存储库。我能够通过使用调试器和 运行 之间的数据库调用来验证。
处理这种情况的最佳方法是什么?是否仅在 t运行sactional 方法之外提取 someObjectRelatedService 调用?
本质上,您需要移动交易的边界。虽然手动刷新交易是一种选择,但我不建议这样做。
如果 SomeObjectRepository2#create(...)
的语义允许,最简单的修复方法是用 @Transactional(isolation = Propagation.REQUIRES_NEW)
.
注释此方法
如果这不可能,我建议进行以下较小的重新设计。首先,我们用一个方法创建一个新的class,它应该执行与所需数据相关的代码:
@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);
}
}
然后我们重写现有代码以使用新的 class:
@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
}
请注意,您必须创建一个新的 class 才能使其正常工作。通过 this
引用的方法调用未被代理,因此 @Transactional
注释不会生效。
进一步注意 newClassInstance
出于同样的原因必须通过 DI 容器注入。
更新现有的一段代码,如下所示:
@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 - 但 t运行sactional 注释阻止了这种情况的发生,它在方法完全 运行 之后更新存储库。我能够通过使用调试器和 运行 之间的数据库调用来验证。
处理这种情况的最佳方法是什么?是否仅在 t运行sactional 方法之外提取 someObjectRelatedService 调用?
本质上,您需要移动交易的边界。虽然手动刷新交易是一种选择,但我不建议这样做。
如果 SomeObjectRepository2#create(...)
的语义允许,最简单的修复方法是用 @Transactional(isolation = Propagation.REQUIRES_NEW)
.
如果这不可能,我建议进行以下较小的重新设计。首先,我们用一个方法创建一个新的class,它应该执行与所需数据相关的代码:
@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);
}
}
然后我们重写现有代码以使用新的 class:
@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
}
请注意,您必须创建一个新的 class 才能使其正常工作。通过 this
引用的方法调用未被代理,因此 @Transactional
注释不会生效。
进一步注意 newClassInstance
出于同样的原因必须通过 DI 容器注入。