在JPA中使用joinTransaction

Sam*_*mah 4 java persistence jpa transactions

以下代码来自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();
   }

}
Run Code Online (Sandbox Code Playgroud)

wyp*_*prz 12

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

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

  1. 如果在事务内部创建持久性上下文,则持久性提供程序将自动将持久性上下文与事务同步.
  2. 如果持久性上下文较早(事务之外或在自端具有一个事务)创建的,持久性上下文可以手动与交易通过调用同步joinTransaction()的上EntityManager接口.一旦同步,持久化上下文将在事务提交时自动刷新.

阅读上述定义后,可能会出现一些问题:

  • 我们怎么知道ShoppingCartImpl参与JTA交易?

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

  • 在这种特殊情况下,我们如何知道应用程序管理的实体管理器

    因为我们使用@PersistenceUnit注释来注入EntityManagerFactory然后手动创建和销毁EntityManager.通过这样做,我们告诉Java EE容器我们不希望自动管理我们的事务(就像事务范围的实体管理器扩展的实体管理器类型一样).

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

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

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

  • 请解释**应用程序不能在多个并发事务中对同一个实体管理器调用 em.joinTransaction()** 有点像场景中发生的情况。 (4认同)