在JPA中使用joinTransaction

以下代码来自JPA规范。 我无法理解为什么em.joinTransaction() createLineItem(int quantity)需要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(); } } 

首先,说几句理论……

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

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

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

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

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

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

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

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

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

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