在我们的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()方法中,我们必须调用em.flush()才能真正命中数据库。事实上,我尝试并发现我们也可以调用em.isOpen()或em.getFlushMode(),好吧,任何“与em相关的”。
我不明白这一点。因为save()在一个事务中,所以我认为在方法结束时,事务将被提交,因此持久性实体管理器会自动刷新。为什么我必须手动刷新它?
谢谢,泽维尔
发布于 2011-09-08 13:34:37
直截了当地说,在您在事务中实际使用javax.transaction.Synchronization之前,将不会有为相关EntityManager注册的对象。
在app-server-land中,我们将创建其中一个对象来执行flush(),并将其注册到javax.transaction.TransactionSynchronizationRegistry或javax.transaction.Transaction。除非有活动的事务,否则无法执行此操作。
这就是它的详细和简短。
是的,应用程序服务器可以很好地保留它提供给有状态bean的资源列表,并将它们自动注册到有状态bean可能启动或参与的每个事务中。这样做的缺点是你完全失去了决定哪些东西进入哪些事务的能力。也许你有2到3个不同的事务在不同的持久化单元上运行,并且正在为一个非常特定的事务在你的扩展持久化上下文中聚合工作。这实际上是一个设计问题,应用服务器应该把这样的决定留给应用本身。
您在事务中使用它,我们将在事务中注册它。这是基本的合同。
附注:根据底层EntityManager的处理方式,对EntityManager的任何持久调用都可能足以在事务结束时导致完全刷新。当然,flush()是最直接、最清晰的,但persist()甚至find()也可以做到这一点。
发布于 2011-09-02 04:39:51
如果使用扩展持久化上下文,则在非事务性方法中对托管实体执行的所有操作都将排队等待写入数据库。一旦在事务上下文中对实体管理器调用flush(),所有排队的更改都会写入数据库。因此,换句话说,当方法退出时,事务性方法本身不会提交更改(就像在CMT中一样),但刷新实体管理器实际上会提交更改。你可以在here上找到这个过程的完整解释
发布于 2014-06-13 17:02:50
因为没有办法知道“何时”客户端完成了会话(扩展范围)。
https://stackoverflow.com/questions/7272354
复制相似问题