2

我知道 em.flush() 的作用是清空内部 SQL 指令缓存,并立即执行到数据库中。 在 JPA/Hibernate 中正确使用 flush()

但是当我使用 JPA em.flush() 将 sql 执行到数据库时,我发现 sql 无法立即执行到数据库。在提交当前事务之前,我无法在数据库中找到数据。

游戏框架中的示例:

em=JPA.em();
Transaction tx=em.getTransaction();
tx.begin();  
em.persist(customer);  
em.flush();  
em.persist(address);  
tx.commit(); 

当我跨过 em.flush(); 行时,我在 em.flush() 行设置了一个断点;
然后,我在数据库中找不到客户数据。

如果我省略了 em.flush(); 提交当前事务时,数据也会进入数据库。那么,em.flush() 有什么用?

4

1 回答 1

0

实体管理器刷新操作将 sql 发送到数据库,但请记住,当事务正在进行时,只有当数据库被告知提交时,通过 sql 发送到数据库的数据才会被持久化。

这是事务期间的一般数据库行为,您可以使用事务来设置数据库操作的原子边界。

即使使用纯 jdbc 而不是任何 orm,您也会看到这种行为,除非为每个发送的 sql 查询启用自动提交。在后台,orm 还使用 jdbc。所以对于单个资源事务(例如单个数据库),通常的习惯用法是先在jdbc连接上设置autoCommit为false,然后通过SQL发送多个insert/updates,然后在连接上调用commit。如果报告了一些异常,则调用回滚。因此,只有在最后一次提交调用被发送到数据库时,数据才会被持久化。

更新

您需要了解没有活动事务的 flush() 是行不通的。还有一个叫做 FlushMode 的东西,它实际上控制何时刷新你可以在 这里查看答案. 理解这一切的关键是,以插入/更新形式发送到数据库的数据不会立即使其持久化,除非事务已提交但同一事务可以访问更改的数据(已更改但未持久)。数据库方面,您可以将其可视化为每个事务的单独区域,其中每个事务都可以更改其内部的数据,但最终进入基础表的数据只有在事务被告知提交后才会这样做。在运行其结果可能受持久上下文状态影响的查询之前,提供程序也会隐式调用刷新。例如,如果您加载一个实体,然后更改其属性,然后对该实体运行查询,然后提供者看到必须首先在其事务中将更改发送到数据库,然后查询实体,以便加载的属性反映更改的属性。但是,在提交事务之前,更改的数据不会保留到实际的表行。

于 2013-10-13T04:34:15.653 回答