【问题标题】:EJB JPA transactionsEJB JPA 事务
【发布时间】:2012-02-12 05:25:48
【问题描述】:

我正在使用 JSF 2.1、EJB 3.1、JPA 2.0、Glassfish 3.1.1 和 NetBeans 7.0.1。

我为每个实体类创建了一个单独的 Facade 类,例如,使用 NetBeans 工具的 UserFacade 和 AddressFacade。这两个实体彼此不相关,完全相互独立。但是,我需要在一个事务期间将它们放入数据库,如果一个无法插入,那么另一个也应该回滚。我怎样才能做到这一点?据我所知,EJB 容器自己管理事务,不允许手动控制事务边界。

【问题讨论】:

  • 我找到了我的问题的答案。如果有人感兴趣,那就是here
  • 你的链接和我的回答有区别吗? =)

标签: jpa transactions ejb


【解决方案1】:

只要您“触摸”同一个实体中的两个实体,事务就会回滚所有内容,更新或删除,但是,您说它们无论如何都彼此不相关,所以我猜您有执行 2 持久化,并且不会在同一个事务范围内。

选项 1

您可以为此做一些简单而丑陋的事情,JPA 中有 @PrePersist 和 @PreUpdate,您可以确保一切都与之前的持久化保持一致。这会造成糟糕的代码库并强制产生不必要的依赖。

选项 2

你可以简单地在用户和地址之间建立一个关系,这是很自然的。

选项 3

第三个选项是使用Bean Managed Transaction

【讨论】:

  • 使用选项 2,您是否暗示两个实体之间存在关系并且级联功能已打开?
  • 是的,这是我的想法。这可能需要一些返工,但为用户提供地址是很自然的。
  • 是的,我同意。即使一个人不打算使用级联功能。很难想到地址和用户不应该有明确关系的用例。
【解决方案2】:

在非常基本的情况下,EJB 的每个公共方法都在一个事务中执行,当方法内抛出异常时,该事务会回滚。

因此,如果您以相同的方法创建两个实体,则这些创建将被包装在一个事务中。

【讨论】:

  • 就我而言,我有两次对 EJB 公共方法的调用。例如,一个方法内部的 userFacade.create(user) 和 addressFacade(address)。但是,userFacade 和 addressFacade 是两个不同 Facade 类的两个不同实例,这两个实体被放入我自己检查的 2 个不同事务中。当一个实体入库失败时,第二个实体成功入库。
  • 你应该重构你的代码,使属于一起的动作在同一个业务方法中执行。
【解决方案3】:

可以自己控制交易。此功能称为 Bean 托管事务 (BMT)。你可以阅读更多关于他们的信息here

您还需要了解TransactionManagement 的东西。 Oracle 在article 中对其进行了描述。

示例:

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class MyEJB implements MyEJBLocal {

  @Resource
  private EJBContext context;

  @PersistenceContext
  private EntityManager em;

  public void doMyAction() {
    UserTransaction transaction = context.getUserTransaction();
    transaction.begin();

    ... create myEntity ...

    em.persist(myEntity);
    transaction.commit();
  }

}

【讨论】:

  • 本教程是针对 J2EE 的,关于他使用 EJB 3.1 已经过时了
  • BMT 是一个非常古老的概念,因此没有理由不赞成;)该链接与 J2EE 相关,但它包含一些代码示例,而新教程则没有。
猜你喜欢
  • 2015-08-18
  • 2014-06-05
  • 1970-01-01
  • 2013-06-21
  • 2020-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多