4 实体管理器和持久化上下文
4.7 应用管理的持久化上下文
当使用管理的久化上下文时,应用直接通过持久化提供商提供的实体管理器 工厂进行交互来管理实体管理器的生命周期以及获得和销毁持久化上下文。
所有这些应用管理的持久化上下文在范围上是被扩展的,以及是跨越多个事 务的。
EntityManager.close()和 isOpen 方法用于管理应用管理的实体管理器和它关 联的持久化上下文的生命周期。
EntityManager.close()方法用于关闭一个操作一个实体管理器并是否它关联 的持久化上下文和其他资源。在 close 方法被调用后,应用不能调用 EntityManager 实例上的任何方法,除了 getTransaction 和 isOpen,否则抛出 IllegalStateException。
如果在事务活动时调用 close 方法,那么持久化上下文仍然被管理直到事务完成。
EntityManager.isOpen 方法表示实体管理器是否是 open 的。isOpen 方法在实 体管理器被关闭前一直返回 true。
扩展的持久化上下文从使用 EntityManagerFactory.createEntityManager 创建 实体管理器开始存在,直到通过 EntityManager.close 关闭实体管理器。从应用管 理的实体管理器获得的扩展持久化上下文是独立的——不随着事务传播。
当使用 JTA 应用管理的实体管理器时,如果在 JTA 事务外创建实体管理器,
那么应用负责调用 EntityManager.joinTransaction 来建立实体管理器与事务的的 关联(如果希望建立关联)。
4.7.1 例子
4.7.1.1 在无状态会话 bean 中使用应用管理的持久化上下文
/*
* Container-managed transaction demarcation is used.
* Session bean creates and closes an entity manager in * each business method.
*/
@Stateless
public class ShoppingCartImpl implements ShoppingCart {
@PersistenceUnit
private EntityManagerFactory emf;
public Order getOrder(Long id) {
EntityManager em = emf.createEntityManager();
Order order = (Order)em.find(Order.class, id);
em.close();
return order;
}
public Product getProduct() {
EntityManager em = emf.createEntityManager();
Product product = (Product) em.createQuery("select p from Product p where p.name = :name")
.setParameter("name", name) .getSingleResult();
em.close();
return product;
}
publicLineItemcreateLineItem(Orderorder,Productproduct,int quantity) {
EntityManager em = emf.createEntityManager();
LineItem li = new LineItem(order, product, quantity);
order.getLineItems().add(li);
em.persist(li);
em.close();
return li; // remains managed until JTA transaction ends
} }
4.7.1.2 在无状态会话 bean 中使用应用管理的持久化上下文
/*
* Container-managed transaction demarcation is used.
* Session bean creates entity manager in PostConstruct * method and clears persistence context at the end of each * business method.
*/
@Stateless
public class ShoppingCartImpl implements ShoppingCart {
@PersistenceUnit
private EntityManagerFactory emf;
private EntityManager em;
@PostConstruct public void init()
em = emf.createEntityManager();
}
public Order getOrder(Long id) {
Order order = (Order)em.find(Order.class, id);
em.clear(); // entities are detached return order;
}
public Product getProduct() {
Product product = (Product) em.createQuery("select p from Product p where p.name = :name")
.setParameter("name", name)
.getSingleResult();
em.clear();
return product;
}
publicLineItemcreateLineItem(Orderorder,Productproduct,int quantity) {
em.joinTransaction();
LineItem li = new LineItem(order, product, quantity);
order.getLineItems().add(li);
em.persist(li);
// persistence context is flushed to database;
// all updates will be committed to database on tx commit em.flush();
// entities in persistence context are detached em.clear();
return li;
}
@PreDestroy
public void destroy() em.close();
} }
4.7.1.3 在有状态会话 bean 中使用应用管理的持久化上下文
//Container-managed transaction demarcation is used
@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);
return li;
}
@Remove
public void destroy() { em.close();
} }
4.7.1.4 带有资源事务的应用管理的持久化上下文
// Usage in an ordinary Java class public class ShoppingImpl { private EntityManager em;
private EntityManagerFactory emf;
public ShoppingCart() {
emf = Persistence.createEntityManagerFactory("orderMgt");
em = emf.createEntityManager();
}
private Order order;
private Product product;
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.getTransaction().begin();
LineItem li = new LineItem(order, product, quantity);
order.getLineItems().add(li);
em.getTransaction().commit();
return li;
}
public void destroy() { em.close();
emf.close();
} }