【问题标题】:How to persist JPA entities even when EJB method throws an exception?即使 EJB 方法抛出异常,如何保持 JPA 实体?
【发布时间】:2011-08-27 13:24:00
【问题描述】:

我有一个 EJB,它的方法(除其他外)保持 JPA 实体。如果方法抛出错误,则事务回滚,实体不持久化。

但是,我确实希望无论在 EJB 方法中可能发生的任何异常情况如何,都可以保留该实体。

如果重要的话,我正在使用 WebSphere 7.0、EJB3.0、JPA 1.0(WAS 中的 OpenJPA)、DB2。

我尝试在 EJB 之上设置@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED);这样,即使没有例外,实体也不会持久化。我也尝试过自己提交事务(em.getTransaction().commit()),但是 getTransaction() 抛出异常(因为事务是由容器管理的)。

【问题讨论】:

    标签: jpa jakarta-ee ejb java-ee-6


    【解决方案1】:

    我不是 EJB 方面的专家,但我这几天一直在处理 JPA 和事务。

    我最近回答了另一个关于实体如何驻留在上下文中的问题,以及它在 Java EE 应用程序中的工作原理,上下文与您的 JTA 事务相关联。

    您可以通过单击here 查看此答案的详细信息。我认为了解上下文如何工作以理解您所描述的问题的性质很有用。

    如果您不提供事务支持,那么从容器的角度来看,没有什么可以持久,因此,您对上下文的更改是暂时的

    您还必须考虑,一旦发生异常,您的上下文就会变得无效,并且其中的实体会被分离。 (有一些例外,比如 NoResultException)。

    因此,从那时起,如果您想提交某些内容,您需要一个新的 JTA 事务,以及一个新的 JPA 上下文,以便能够提交对数据库的更改。

    正如我所说,我不是 EJB 专家,但如果您的方法因异常而失败,并且您仍想通过重新调用该方法再次重试事务,那么您可以强制创建一个新事务每次调用该方法时,您都将创建一个新的 JPA 上下文。

    另一方面,如果您希望保留对实体的修改,而不考虑方法中的异常,那么您可能会考虑将更新实体的代码移动到定义的新 EJB 方法以启动每次调用新事务 (TransactionAttributeType.REQUIRES_NEW)。

    当第二个内部方法完成时,您在事务上的工作将自动刷新到数据库中,而不管您的 EJB 外部方法是否失败。

    基本上,您将为您的实体提供一个新的上下文,并将这种上下文链接到一个新事务,范围为在内部方法完成时提交。

    据我所知,EJB 容器中的自然行为是任何方法都会加入已经存在的事务,从我的角度来看,这是您可能希望阻止的。

    另一种选择:如果您想使用不同的事务支持来控制您的上下文,那么您可能会考虑提供一个基于资源本地的持久性单元,并且您可以手动实例化您的实体管理器并根据需要控制事务范围。但老实说,这对我来说听起来不是一个好主意,至少在你描述的问题的背景下不是。

    【讨论】:

      【解决方案2】:

      使用 bean 管理的事务。

      @Stateless
      @TransactionManagement(TransactionManagementType.BEAN)
      public class MyEJB {
        @PersistenceContext(unitName="...")
        private EntityManager _em;
        @Resource
        private UserTransaction _utx;
      
        public void myEJBMethod() {
          _utx.begin();
          // Use _em
          _utx.commit();
          // Do other work that might throw an exception.
        }
      }
      

      或者,按照 edalorzo 的建议使用 TransactionAttributeType.REQUIRES_NEW。

      【讨论】:

      • 还必须重新配置 ejb-jar.xml 文件,其中(至少在我的情况下)指定了 EJB 事务类型。
      • 是的,如果您使用的是 ejb-jar.xml 而不是注释,则需要更新 XML 以指定事务类型。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-09
      • 2019-04-07
      • 2019-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多