以下代码来自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();
}
}
答案 0 :(得分:12)
首先,说几句理论......
应用程序管理的实体管理器以两种方式之一参与JTA事务。
joinTransaction()
接口上的EntityManager
来手动将持久性上下文与事务同步。一旦同步,持久化上下文将在事务提交时自动刷新。阅读上述定义后,可能会出现一些问题:
我们如何知道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