Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在JPA/Hibernate中正确使用flush()_Java_Hibernate_Jpa_Transactions_Persistence - Fatal编程技术网

Java 在JPA/Hibernate中正确使用flush()

Java 在JPA/Hibernate中正确使用flush(),java,hibernate,jpa,transactions,persistence,Java,Hibernate,Jpa,Transactions,Persistence,我正在收集有关flush()方法的信息,但我不太清楚何时使用它以及如何正确使用它。从我读到的内容来看,我的理解是持久性上下文的内容将与数据库同步,即。E发布未完成的语句或刷新实体数据 现在我得到了以下两个实体的场景A和B(一对一的关系,但不是由JPA强制执行或建模)A有一个手动设置的复合主键,还有一个自动生成的标识字段recordId。此recordId应作为a的外键写入实体B。我在单个事务中保存A和B。问题是自动生成的值A.recordId在事务中不可用,除非我在调用A上的em.persist

我正在收集有关flush()方法的信息,但我不太清楚何时使用它以及如何正确使用它。从我读到的内容来看,我的理解是持久性上下文的内容将与数据库同步,即。E发布未完成的语句或刷新实体数据

现在我得到了以下两个实体的场景
A
B
(一对一的关系,但不是由JPA强制执行或建模)
A
有一个手动设置的复合主键,还有一个自动生成的标识字段
recordId
。此
recordId
应作为
a
的外键写入实体
B
。我在单个事务中保存
A
B
。问题是自动生成的值
A.recordId
在事务中不可用,除非我在调用
A
上的
em.persist()
后显式调用
em.flush()
。(如果我有一个自动生成的标识PK,那么该值将直接在实体中更新,但这里不是这样。)


在事务中使用em.flush()会造成任何伤害吗?

可能em.flush()的确切细节取决于实现。 总之,像Hibernate这样的JPA提供程序通常可以缓存它们应该发送到数据库的SQL指令,直到您实际提交事务为止。 例如,调用
em.persist()
,Hibernate会记住它必须进行数据库插入,但在提交事务之前不会实际执行指令。好吧,这主要是出于性能原因

在某些情况下,您希望立即执行SQL指令;通常,当您需要某些副作用的结果时,例如自动生成的密钥或数据库触发器

em.flush()
所做的是清空内部SQL指令缓存,并立即对数据库执行它

一句话:不会造成任何伤害,只会对性能造成(轻微)影响,因为您正在覆盖JPA提供程序关于向数据库发送SQL指令的最佳时间的决定。

实际上,
em.flush()
,所做的不仅仅是发送缓存的SQL命令。它尝试将持久性上下文同步到基础数据库。如果缓存包含要同步的集合,则可能会在进程上消耗大量时间

小心使用它

在事务中使用em.flush()会造成任何伤害吗

是的,它可能会在数据库中保留锁的时间超过必要的时间

通常,在使用JPA时,您将事务管理委托给容器(也称为CMT-使用@Transactional annotation on business methods),这意味着在输入方法时会自动启动事务,并在最后提交/回滚。如果让EntityManager处理数据库同步,sql语句的执行只会在提交之前触发,从而导致数据库中的短期锁定。否则,手动刷新的写入操作可能会在手动刷新和自动提交之间保留锁,根据剩余的方法执行时间,锁可能会很长


请注意,某些操作会自动触发刷新:对同一会话执行本机查询(必须刷新EM状态才能由SQL查询访问),使用本机生成的id插入实体(由数据库生成,因此必须触发insert语句,以便EM能够检索生成的id并正确管理关系)

他所说的。EM.flush()行为响应java.io.Flushable.flush(),其中所有缓冲数据都发送到适当的目的地。if flush()将数据发送到数据库?如果在此之后引发异常会发生什么?实体管理器会回滚所有内容吗?即使是在第一次刷新中写入的数据?flush()会向数据库发送SQL指令,如INSERT、UPDATE等。它不会发送提交,因此如果在刷新()之后出现异常您仍然可以有一个完整的回滚。您可以回滚DB,但它不会回滚对象的任何更改,例如,自动递增的“版本”、自动生成的ID等。此外,实体管理器在回滚后将关闭。请注意,如果您尝试将对象合并到另一个会话,则自动增加“版本”的PAR。ticular可能会导致OptimisticLockException。除了触发副作用外,使用flush()的另一个原因是如果您希望能够使用JPQL/HQL(例如在测试中)读取数据库中操作的效果。JPA在执行这些查询时无法使用缓存数据,因此只会读取数据库中实际存在的内容。