【发布时间】:2019-09-27 11:10:02
【问题描述】:
我有一个注解为@Transactional 的事件处理程序方法,该方法调用同一类中事件的实现。
此事件会进行一些检查,并根据结果执行某些操作,或者更改状态并抛出 RuntimeException。
如果由于检查而改变状态,我需要保持状态但事件失败以重试。
状态改变方法在另一个类中,方法用@Transactional(propagation = Propagation.REQUIRES_NEW)注解。
我希望由于内部事务完成,状态更改会保持不变,并且事件事务会回滚。
我看到的是状态更改也回滚了,但是当我明确告诉它为状态更改创建新事务时,我不明白为什么它会回滚所有内容。
请记住,这是一个遗留项目,因此不可能对架构进行重大更改。
我尝试调试事务更改,调试器确实跳转到新事务的提交,但由于某种原因它没有持久化到数据库中。
public class t implements it {
// Do initialisation and class injection. Y is constructor injected
private final Y y;
public t(Y y) {
this.y = y;
}
@Override
@Transactional
public void handleEvent(EventContext context) {
switch (context.getEventType()) {
case event:
validate(context);
break;
}
}
private void validate(EventContext context) {
Object o = crudService.findByProperty(context.getObjectUuid());
if (!o.check) {
y.changeStatus(ERROR);
// break for retry
throw new RuntimeException("Some serious message log");
} else {
// do some stuff
}
}
}
public class Y implements IY {
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void changeStatus(Object o, String status) {
// We do a lot more here then just change this status because of inheriting objects but for the sake of the argument, change status
o.status = status;
}
}
这是代码所做工作的粗略草图。
我希望状态更改会持续存在,因为在 propogation_new 事务开始时外部事务会暂停。我还可以看到在 Spring 的事务代码中调用了提交,但由于某种原因它没有持久化到数据库中。
如果我删除运行时异常的抛出,它可以工作,但事件完成,这是不需要的。
我在这张照片中缺少什么?希望你能帮忙。
谢谢!
编辑
我想我找到了问题所在,稍微更改了示例代码以使其更清晰。
changeStatus 更改 crudService 返回的对象的状态。在实际应用中,我们会做更多的更改,因为依赖对象 o 的对象也需要根据状态更改进行更改。
因为外层事务的状态为o,那是否意味着如果我在内层事务内部进行更改,因为外层事务持有引用,它会回滚到那个状态,而不是持久化内层事务的变化?
【问题讨论】:
-
该代码无法编译:changeStatus 是实例方法,而不是静态方法。 Y是春豆吗? t 对象如何获得 Y 的实例?
-
是的,Y 是春豆。它通过 x 的构造函数注入。为澄清添加了构造函数。
标签: java spring-boot spring-transactions