为什么要在扩展的PersistenceContext中手动刷新()EntityManager? [英] Why do we have to manually flush() the EntityManager in a extended PersistenceContext?

查看:226
本文介绍了为什么要在扩展的PersistenceContext中手动刷新()EntityManager?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我们的J2EE应用程序中,我们使用EJB-3状态bean来允许前端代码创建,修改和保存持久性实体(通过JPA-2管理)。

In our J2EE application, we use a EJB-3 stateful bean to allow the front code to create, modify and save persistent entities (managed through 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(),我们在数据库中不插入任何内容。

Very important, to avoid too early commits, only the save() method is within a transaction, so if we call create(), we insert nothing in the database.

奇怪的是,在 save()方法中,我们必须调用 em.flush ()为了真正打数据库。实际上,我尝试发现我们也可以调用 em.isOpen() em.getFlushMode()任何em相关的任何东西。

Curiously, in the save() method, we have to call em.flush() in order to really hit the database. In fact, I tried and found that we can also call em.isOpen() or em.getFlushMode(), well anything that is "em-related".

我不明白这一点。由于 save()在事务中,我认为在方法结束时,事务将被提交,因此持久性实体管理器会自动刷新。为什么要手动刷新?

I don't understand this point. As save() is in a transaction, I thought that at the end of the method, the transaction will be committed, and so the persistent entity manager automatically flushed. Why do I have to manually flush it?

谢谢,
Xavier

Thanks, Xavier

推荐答案

为了直接和金属,在实际使用使用前,将不会有EntityManager注册的 javax.transaction.Synchronization 对象

To be direct and to the metal, there will be no javax.transaction.Synchronization objects registered for the EntityManager in question until you actually use it in a transaction.

我们在app-server-land中将创建其中一个对象来执行 flush()并注册它与 javax.transaction.TransactionSynchronizationRegistry javax.transaction.Transaction 。除非有活动的交易,否则这是无法做到的。

We in app-server-land will create one of these objects to do the flush() and register it with the javax.transaction.TransactionSynchronizationRegistry or javax.transaction.Transaction. This can't be done unless there is an active transaction.

这是很长的和不足的。

是的,一个应用服务器可以很好地保存一个资源列表,它给予状态bean,并在有状态bean可能启动或参与的每个事务中自动注册。缺点是你完全失去了决定哪些事情的能力去哪些交易。也许你有一个2或3个不同的事务在不同的持久性单元上运行,并且在一个非常特定的事务中聚合在扩展持久性上下文中的处理。这真的是一个设计问题,应用服务器应该将这样的决定留给应用程序本身。

Yes, an app server could very well keep a list of resources it gave the stateful bean and auto-enroll them in every transaction that stateful bean might start or participate in. The downside of that is you completely lose the ability to decide which things go in which transactions. Maybe you have a 2 or 3 different transactions to run on different persistence units and are aggregating the work up in your Extended persistence context for a very specific transaction. It's really a design issue and the app server should leave such decisions to the app itself.

您在事务中使用它,我们将其注册到事务中。这是基本的合同。

You use it in a transaction and we'll enroll it in the transaction. That's the basic contract.

侧注,根据底层的EntityManager的处理方式,任何持久调用EntityManager 可能足以在事务结束时导致完整的刷新。当然, flush()是最直接和清晰的,但是一个 persist()甚至一个 find()可能会这样做。

Side note, depending on how the underlying EntityManager is handled, any persistent call to the EntityManager may be enough to cause a complete flush at the end of the transaction. Certainly, flush() is the most direct and clear but a persist() or even a find() might do it.

这篇关于为什么要在扩展的PersistenceContext中手动刷新()EntityManager?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆