3

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

<bean id="MyServiceImpl"
          class="com.test.impl.MyServiceImpl">
    <jpa:context property="em" unitname="mypu" />
    <tx:transaction method="*" value="Required" />
</bean>
<service id="MyService" ref="MyServiceImpl" interface="com.test.api.MyService" />   

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

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

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

4

2 回答 2

1

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

于 2013-10-02T13:20:40.797 回答
0

1:几年前我也问过同样的问题。在 Spring 中,您可以指定某些事务应该导致回滚,而在蓝图中您不能这样做。过了一会儿,我找到了“清洁代码”这本书,并阅读了“错误处理”一章。我开悟了。我并没有真正尝试像书中所说的那样写下来。我认为在您阅读之后,如果这是正确的行为,您将获得一些有用的基本想法来建立您的观点。

2:可以有两种选择:

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

3:这也让我感到困惑:)。您确定在坚持父母之后但在调用孩子之前不抛出异常吗?可能存在 ASM,如果存在,则 jta-blueprint 存在错误...需要进行调试以找出发生的情况。

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

于 2013-09-26T15:43:51.727 回答