【问题标题】:EJB3 - handling RollBackExceptionsEJB3 - 处理 RollBackExceptions
【发布时间】:2010-10-14 23:37:32
【问题描述】:

我有一个 EJB3 应用程序,它包含一些用于访问数据库的 EJB,并通过会话 Bean 作为 Web 服务公开。

现在我需要找出两件事:

1) 有什么方法可以阻止 SQL 异常导致 Web 服务抛出 SOAP 错误?事务由容器处理,当前 sql 异常会导致引发 RollBackException,因此事务会回滚(期望的行为)并且 Web 服务会引发错误(不需要)。

2) 我希望扩展 web 服务,使其能够接收实体列表,并且会话 bean 能够持久化。但是,我希望每个实体都在自己的事务中执行,这样如果一个实体失败,其他实体不会受到影响(同样,Web 服务不应该出错)。

对于 (1) 我试图捕获 RollBackException,但我认为这是在另一个线程的某个地方抛出的,因为永远不会到达 catch 块。我假设(2)我需要研究用户事务,但首先希望容器来管理它,其次不知道如何强制使用用户事务。

谢谢。

【问题讨论】:

    标签: java transactions jakarta-ee persistence ejb-3.0


    【解决方案1】:

    不,您可以使用容器管理的事务来完成所有这些工作(这绝对是可取的,因为管理事务很痛苦)。

    解决方案的要点是创建第二个 EJB,仅具有本地接口和您想要的事务语义。然后,Web 服务直接调用的“公共”ejb 通过其本地接口调用第二个 ejb 以执行实际工作。

    类似的东西:

    public class MyPublicEjb {
      @EJB
      private MyPrivateImpl impl;
    
      public void doSomething() {
        try {
          impl.doSomething();
        } catch(TXRolledBack) {
          // handle rollback ...
        }
      }
    }
    

    我知道这看起来有点难看,但相信我,这比直接操纵交易要好得多。

    【讨论】:

    • 需要注意的是私有 EJB 需要一个 @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 注释(否则我们会遇到与之前相同的情况,因为事务在调用 EJB 上的作用域)这是有效的。谢谢。
    【解决方案2】:

    对于 (1):调试您的代码以找出异常被抛出的位置以及导致它的原因。然后在那里处理异常。

    对于 (2):用 beginTransaction() 和 commit() 包装每个实例。

    for(each Entity){
        try{
            //begin transaction
            //save entity
            //commit
        } catch(Exception e) {
             //handle Exception, but continue on
        }
    }
    

    【讨论】:

    • 正如我所说的——异常似乎是从一个单独的线程中抛出的——或者至少在我的代码完成它正在做的事情之后。具体来说,在抛出异常时,我的代码已将控制权返回给应用服务器 - 即无法捕获它。
    • 关于第二点,我很清楚这类问题的一般解决方案——只是没有具体说明如何在 EJB3 中解决。如何使用 EntityManager 开始和提交事务?如何获取未绑定到容器管理事务的 EntityManager?
    猜你喜欢
    • 2010-12-03
    • 2010-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-04
    • 2012-01-08
    • 1970-01-01
    • 2011-05-02
    相关资源
    最近更新 更多