在JPA中使用joinTransaction

时间:2014-06-27 00:32:46

标签: java jpa transactions persistence

以下代码来自JPA规范。我无法理解为什么em.joinTransaction()需要createLineItem(int quantity)

任何人都可以提供合适的解释吗?

@Stateful
public class ShoppingCartImpl implements ShoppingCart {

   @PersistenceUnit
   private EntityManagerFactory emf;
   private EntityManager em;
   private Order order;
   private Product product;

   @PostConstruct
   public void init() {
      em = emf.createEntityManager();
   }

   public void initOrder(Long id) {
      order = em.find(Order.class, id);
   }

   public void initProduct(String name) {
      product = (Product) em
            .createQuery("select p from Product p where p.name = :name")
            .setParameter("name", name).getSingleResult();
   }

   public LineItem createLineItem(int quantity) {
      em.joinTransaction();
      LineItem li = new LineItem(order, product, quantity);
      order.getLineItems().add(li);
      em.persist(li);
      return li;
   }

   @Remove
   public void destroy() {
      em.close();
   }

}

1 个答案:

答案 0 :(得分:12)

首先,说几句理论......

应用程序管理的实体管理器以两种方式之一参与JTA事务。

  1. 如果在事务内部创建了持久性上下文,则持久性提供程序将自动将持久性上下文与事务同步。
  2. 如果先前创建了持久性上下文(在事务之外或在已经结束的事务中),则可以通过调用joinTransaction()接口上的EntityManager来手动将持久性上下文与事务同步。一旦同步,持久化上下文将在事务提交时自动刷新。
  3. 阅读上述定义后,可能会出现一些问题:

    • 我们如何知道ShoppingCartImpl参与JTA交易?

      因为该类已使用@Stateful(或@Stateless)注释进行注释因此,目的是在Java EE环境中执行该类,该环境默认使用JTA事务。如果一个类在Java SE环境中执行,则不需要这样的注释。

    • 我们如何知道在这种特殊情况下使用应用程序管理的实体管理器
      因为我们使用@PersistenceUnit注释来注入{ {1}}然后手动创建并销毁EntityManagerFactory。通过这样做,我们告诉Java EE容器我们不希望自动管理我们的事务(就像事务范围的实体管理器扩展实体管理器类型一样) )。

    • 为什么EntityManager方法需要em.joinTransaction()

      通过调用createLineItem,我们通知应用程序管理的持久化上下文它应该与当前的JTA事务同步。如果没有这样的调用,当事务提交时(em.joinTransaction()方法结束时),Order的更改将不会刷新到底层数据库。

      注意:由于createLineItem实例是线程安全的而EntityManagerFactory实例不是,因此应用程序不得在多个并发事务中对同一实体管理器调用EntityManager