【问题标题】:EJB 3 transaction rollback issueEJB 3 事务回滚问题
【发布时间】:2016-07-29 12:08:08
【问题描述】:

我有以下代码:

        @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
        public Car prepareCar(Data data) throws CarServiceException{
          Car car = null;
          try {
            car = carManagerBean.createCar(data);
            Driver driver = createDriver();
            car.setDriver(driver);
          } catch (Exception e) {
            LOGGER.error(e.getMessage, e);
            context.setRollbackOnly();
            throw new CarServiceException(e);
          }
          return car;
         }

问题是如果try部分出现一些问题(例如SQLServerException),catch部分没有被执行,CarServiceException也没有被抛出。有人知道这段代码可能有什么问题吗?但无论如何,事务都会回滚。 只有当我移动 try-catch 块来包装方法调用时它才有效。

【问题讨论】:

    标签: java hibernate ejb ejb-3.0


    【解决方案1】:

    您想在事务之外捕获异常。这样做:

    @Stateless
    public class CarServiceDelegate {
    
       @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
       public Car prepareCar(Data data) throws CarServiceException{
          Car car = carManagerBean.createCar(data);
          Driver driver = createDriver();
          car.setDriver(driver);
          return car;
       }
    }
    
    public class CarService {
    
       @EJB
       private CarServiceDelegate carServiceDelegate;
    
       public Car prepareCar(Data data) {
           try {
               return carServiceDelegate.prepareCar();
           } catch (Exception e) {
            // You will catch it here, when the transaction is done.
            LOGGER.error(e.getMessage, e);
            throw new CarServiceException(e);
          }
       }
    
    }
    

    我将为您提供有关 EJb 异常的哪一部分要求将异常传播到事务之外的最新信息。在@Asynchronous 调用中会发生类似的行为(异常被抑制)。

    【讨论】:

    • 会自动回滚,根据EJB规范,如果出现异常(除非是应用异常,rollback=false),事务会回滚。
    • 应用程序异常根据规范默认为rollback=false,以前的EJB规范在运行时和检查异常之间有所不同。任何 RuntimeException 将 Tx 标记为回滚,已检查的异常不会标记它,您需要在应用程序代码中调用 setRollbackOnly。
    【解决方案2】:

    请记住,如果您的 catch 块本身引发异常,它将不会到达重新引发异常的段。请注意,根据文档,如果事务不再处于活动状态,setRollbackOnly() 可以抛出 IllegalStateException。您可能希望将 catch 块包装在另一个 try/catch 块中以发现这一点。

    【讨论】:

    • 它甚至不执行 catch 块中的第一行:LOGGER.error(e.getMessage, e);
    • 这是不可能的,除非代码实际上没有抛出异常。尝试在 try 块的末尾插入一个调试日志条目。
    猜你喜欢
    • 1970-01-01
    • 2012-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-21
    相关资源
    最近更新 更多