OSGi中的事务回滚

我有一个OSGi包,我在其中声明了一个服务并用蓝图注入一个事务:

     

在这个服务中,我有两个方法,每个方法都在数据库中写入数据,如下所示:

 public void createParent() throws MyException { Parent parent = new Parent(); ... // Set parent fields em.persist(parent); createChild(); // Checks that could throw MyException } public void createChild() throws MyException { Child child = new Child(); ... // Set child fields em.persist(child); // Checks that could throw MyException } 

我的问题如下:

  1. 如果我在em.persist(parent);之间的createParent方法中抛出运行时exceptionem.persist(parent);createChild(); 事务回滚(正如我所料)并且父级不会保留在数据库中。 但是,如果在同一点上我抛出MyException(这是一个已检查的exception),则事务提交并且父持久化。 我在Aries邮件列表中看到蓝图声明性事务中声明的(已检查)exception不会触发回滚。 有没有办法配置此行为并指定我希望我的exception在抛出时回滚事务?
  2. 如果我在createChild方法中抛出运行时exception(在em.persist(child); ),则child不会在数据库中em.persist(child); ,但是父级是持久的,就好像这两个方法在两个不同的事务中运行一样。 这是为什么? 在createParent启动的事务中不应该createChild join吗?
  3. 如果我在调用createChild之后在createParent方法中抛出运行时exception,我会得到与第2点相同的行为(即,父级是持久化的,而子级不是持久化的),这使我更加困惑,因为即使我假设createChild启动了新事务然后在createParent中抛出exception时不应该回滚。
  4. 如果在上面的第2点和第3点中,两种方法处于不同的服务中,那么一切都按预期工作,即。 任何方法中抛出的运行时exception都会回滚整个事务。

有人可以解释一下上述行为吗?

从Aries邮件列表中获得一些帮助后,结果发现问题出在数据源配置中,而不是蓝图配置中。 虽然我使用MysqlXADataSource作为驱动程序类,但数据源服务已注册为javax.sql.DataSource而不是javax.sql.XADataSource ,这是弄乱我的事务。

1:几年前我问了同样的问题。 在Spring中,您可以指定某些事务应该导致回滚,而有些事务则不会,在蓝图中您无法执行此操作。 过了一会儿,我找到了“清洁代码”一书,并阅读了“error handling”一章。 我开悟了。 我并没有像书中所说的那样写下来。 我想在你阅读之后,如果这是一个正确的行为,你会得到一些有用的基本想法来建立你的意见。

2:可以有两种选择:

  • 您在persist函数之前抛出exception。 您在父级中捕获exception。 如果函数是从外部调用的,那么子函数只包含拦截逻辑,当来自子节点的调用以任何方式返回父节点时,不会回滚。 想想class级包装。 至少如果你不使用字节码操作或运行时类inheritance(但只有java代理类),你不能以一种截取函数内部函数调用的方式编写一个类。 可能Aries与ASM试图做到这一点(ASM-4存在),但我个人不喜欢这种技巧。
  • 你发现了一个错误

3:这也让我感到困惑:)。 您是否确定在父母坚持但在致电孩子之前不会抛出exception? 可能ASM存在,如果那是jta-blueprint有一个bug …需要调试以找出发生了什么。

4:很高兴听到它可以以某种方式工作:)