4

如果我有一个带有 @ApplicationException(inherited = true, rollback = true) 的异常,但我希望子类不回滚。我可以只用@ApplciationException(rollback = false) 注释子类吗?或者那行不通?规范似乎没有说,我可以找到。

4

2 回答 2

6

EJB 3.1 规范 (JSR 318) 确实在第 14.2.1 节中解释了这一点。有一个例子:

In the following example :
@ApplicationException(rollback=true)
public class ExceptionA extends RuntimeException
public class ExceptionB extends ExceptionA
@ApplicationException(inherited=false, rollback=false)
public class ExceptionC extends ExceptionB
public class ExceptionD extends ExceptionC

ExceptionA is an application exception with transaction rollback.
ExceptionB is an application exception with transaction rollback.
ExceptionC is an application exception without transaction rollback.
ExceptionD is not an application exception.
于 2013-01-23T19:48:07.060 回答
4

JSR 220没有明确说明在这种情况下应该发生什么。它确实指定application-exception部署描述符元素将覆盖特定 EJB 的任何带注释的值:

应用程序异常不会自动导致将事务标记为回滚,除非 ApplicationException 注释应用于异常类并指定回滚元素值 true 或异常的应用程序异常部署描述符元素将回滚元素指定为 true。应用程序异常部署描述符元素的回滚子元素可以显式指定以覆盖由 ApplicationException 注释指定或默认的回滚值

@TransactionAttribute这与其他 Java EE 组件(等)的注解如何工作相结合@ConcurrencyManagement,将导致人们强烈假设子类@ApplicationException注解将覆盖其父类的注解。我通过一个简单的测试确认了这种情况(显示的代码不完整):

@ApplicationException(inherited = true, rollback = true)
public class MyBaseException extends RuntimeException {
    // Constructors
}

public class MySubException1 extends MyBaseException {
    // Constructors
}

@ApplicationException(rollback = false)
public class MySubException2 extends MyBaseException {
    // Constructors
}

@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@Path("/misc/exception")
@Produces(MediaType.APPLICATION_JSON)
public class ExceptionResourceImpl {
   @Inject
   private BaseDAO baseDAO;

   public ExceptionResourceImpl() {
      super();
   }

   @GET
   @Path("/app/{id}")
   public Response getApplicationException(@PathParam("id") final String id) {
      final PaymentTypeModel model = new PaymentTypeModel();
      model.setPayment("Key" + System.currentTimeMillis());

      if ("1".equals(id)) {
         baseDAO.create(model);
         throw new MySubException1(
               "Throwing sub exception 1, default annotation behaviour");
      } else if ("2".equals(id)) {
         baseDAO.create(model);
         throw new MySubException2(
               "Throwing sub exception 2, overrides annotation behaviour");
      } else {
         return Response.status(Status.BAD_REQUEST)
               .entity("Must supply id of 1 or 2").build();
      }
   }
}

结果:

  • 请求 /misc/exception/app/1 会导致屏幕上出现错误,并且没有记录保存到数据库中。
  • 请求 /misc/exception/app/2 会导致屏幕上出现错误,但记录保存到数据库中,也就是处理了不回滚事务的注释覆盖MySubException2

* 编辑 *

JSR 318ApplicationException确实通过使用示例阐明了继承注释的行为。

在以下示例中:

@ApplicationException(rollback=true) 公共类 ExceptionA 扩展 RuntimeException

公共类 ExceptionB 扩展了 ExceptionA

@ApplicationException(inherited=false, rollback=false) 公共类 ExceptionC 扩展 ExceptionB

公共类 ExceptionD 扩展了 ExceptionC

ExceptionA 是具有事务回滚的应用程序异常。ExceptionB 是具有事务回滚的应用程序异常。ExceptionC 是没有事务回滚的应用程序异常。ExceptionD 不是应用程序异常

这证实了我最初的陈述和测试。

于 2013-01-23T19:18:10.533 回答