以下代码来自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();
}
}
最佳答案
首先,几句理论...
应用程序管理的实体管理器以两种方式之一参与JTA事务。
joinTransaction()
接口(interface)上调用EntityManager
将持久性上下文与事务手动同步。一旦同步,持久化上下文将在事务提交时自动刷新。 阅读以上定义后,可能会出现一些问题:
ShoppingCartImpl
参与了JTA事务?因为该类已使用@Stateful
(或@Stateless
)注释进行了注释,因此其目的是在默认使用JTA事务的Java EE环境中执行该类。如果一个类将在Java SE环境中执行,则不需要此类注释。 @PersistenceUnit
批注注入(inject)EntityManagerFactory
,然后手动创建和销毁EntityManager
。通过这样做,我们告诉Java EE容器我们不希望自动管理事务(例如在事务范围的实体管理器或扩展的实体管理器类型的情况下)。 em.joinTransaction()
方法中需要createLineItem
?通过调用em.joinTransaction()
,我们通知应用程序管理的持久性上下文它应该与当前JTA事务同步。如果没有这样的调用,则在事务提交时(在Order
方法的结尾),对createLineItem
的更改将不会刷新到基础数据库。注意:由于EntityManagerFactory
实例是线程安全的,而EntityManager
实例不是线程安全的,因此应用程序不得在多个并发事务中的同一实体管理器上调用em.joinTransaction()
。