在我们的J2EE应用程序中,我们使用EJB-3有状态bean来允许前端代码创建,修改和保存持久性实体(通过JPA-2管理)。
看起来像这样:
@LocalBean @Stateful @TransactionAttribute(TransactionAttributeType.NEVER) public class MyEntityController implements Serializable { @PersistenceContext(type = PersistenceContextType.EXTENDED) private EntityManager em; private MyEntity current; public void create() { this.current = new MyEntity(); em.persist(this.current); } public void load(Long id) { this.current = em.find(MyEntity.class, id); } @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) public void save() { em.flush(); } }
非常重要的是,为了避免过早提交,只有save()方法位于事务内,因此,如果调用create(),则不会在数据库中插入任何内容。
save()
create()
奇怪的是,在save()方法中,我们必须调用em.flush()才能真正访问数据库。实际上,我尝试过发现,我们也可以调用em.isOpen()或em.getFlushMode(),以及与“ em有关”的任何东西。
em.flush()
em.isOpen()
em.getFlushMode()
我不明白这一点。与save()事务中的情况一样,我认为在方法结束时将提交事务,因此持久性实体管理器会自动刷新。为什么我必须手动冲洗它?
谢谢,Xavier
是直接和金属,不会有javax.transaction.Synchronization问题登记EntityManager的对象,直到你真正 使用 它 的 交易。
javax.transaction.Synchronization
我们在app-server- land中将创建这些对象之一来执行flush()并将其注册到javax.transaction.TransactionSynchronizationRegistry或javax.transaction.Transaction。除非有活动的交易,否则无法完成此操作。
flush()
javax.transaction.TransactionSynchronizationRegistry
javax.transaction.Transaction
这就是它的长短。
是的,应用服务器可以很好地保存它提供给有状态Bean的资源列表,并自动将其注册到有状态Bean可能启动或参与的每个事务中。其缺点是,您完全失去了决定执行哪些操作的能力在其中进行交易。也许您有2或3个不同的事务要在不同的持久性单元上运行,并在扩展持久性上下文中汇总非常特定的事务的工作。这实际上是一个设计问题,应用服务器应将此类决策留给应用本身。
您在交易中使用它,我们将其注册在交易中。那是基本合同。
旁注,根据底层EntityManager的处理方式,对EntityManager的 任何 持久调用都 可能 足以在事务结束时引起完全刷新。当然,这flush()是最直接,最明确的方法,但一个persist()甚至一个find()都可以。
persist()
find()