在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事务。
- 如果在事务内部创建持久性上下文,则持久性提供程序将自动将持久性上下文与事务同步。
- 如果先前创建了持久性上下文(在事务之外或在已经结束的事务中),则可以通过在
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()
。