2010-03-02 93 views
27

我在EJB3无状态会话bean中使用CMT。另外我创建了自己的Exception,注释“@ApplicationException(rollback = true)”。EJB3事务回滚

  1. 当我想要回滚事务时,是否必须使用“context.setRollbackOnly()”?

  2. 我可以通过在bean中的公共方法内引发异常来回滚事务吗?

  3. 如果是这样(的答案,Q#2是肯定的),我必须在方法声明异常抛出异常的方法的还是会足以随便扔在方法内部异常和处理它在同一个方法里面呢? (我不想传播异常到一个新的水平。我只是想回滚除外。)提前

感谢。 ;)

回答

62

首先,没有回滚异常,它是事务的回滚。

  1. 如果您抛出异常与@ApplicationException(rollback=true),您不必手动回滚事务。 Context.setRollbackOnly()强制容器回滚事务,如果没有异常。
  2. 检查异常本身不回滚事务。它需要有注释@ApplicationException(rollback=true)。如果异常是RuntimeException,并且未捕获异常,则会强制容器回滚事务。但要小心,容器将在这种情况下放弃EJB实例。
  3. 正如2.)所述,如果您抛出一个RuntimeException,交易将自动回滚。如果您在代码中捕获了已检查的异常,则必须使用setRollbackOnly来回滚事务。

如需进一步信息,请查看免费书籍Mastering EJB。它非常好地描述了回滚场景,并且可以免费下载。

+0

“如果您在代码中捕获了已检查的异常,则必须使用setRollbackOnly来回滚事务。” 你也可以抛出相同的异常并回滚事务吗? – 2010-03-03 03:36:03

+0

您可以使用throws子句抛出相同的异常,但事务不会回滚。如果您想在这种情况下回滚事务,则必须将@ApplicationException(rollback = true)添加到您的异常中。另一种方法是将检查的异常封装在未经检查的异常(例如RuntimeException)中。但是这种方式并不是首选,因为如果抛出RuntimeException,容器会放弃bean实例并创建一个新实例。 – Steve 2010-03-03 06:30:05

+1

我只是在类似的原因看这个答案,并希望指出,你链接到的书不再在该网站提供完整的,它是从2006年,所以它是非常过时的,可能没有太多用于JEE5和JEE6上下文。 – BillR 2012-09-08 00:24:44

0

关于如何防止检查异常的注释性声明导致抛出时的回滚被传播到“上层”的问题尚未在这里得到解答。

我认为这将需要一个围绕所讨论的EJB的包装,它吞噬了抛出的异常。 (换句话说:我认为自定义异常必须针对方法边界抛出(因此在方法内处理内部并没有捕获到&)并传播以获取事务效果 - 同时也会导致EJB实例的破坏。)