Java JPA/Hibernate中flush()的正确使用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4275111/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Correct use of flush() in JPA/Hibernate
提问by MicSim
I was gathering information about the flush() method, but I'm not quite clear when to use it and how to use it correctly. From what I read, my understanding is that the contents of the persistence context will be synchronized with the database, i. e. issuing outstanding statements or refreshing entity data.
我正在收集有关 flush() 方法的信息,但我不太清楚何时使用它以及如何正确使用它。从我读到的,我的理解是持久化上下文的内容会与数据库同步,即发出未完成的语句或刷新实体数据。
Now I got following scenario with two entities A
and B
(in a one-to-one relationship, but not enforced or modelled by JPA). A
has a composite PK, which is manually set, and also has an auto-generated IDENTITY field recordId
. This recordId
should be written to entity B
as a foreign-key to A
. I'm saving A
and B
in a single transaction. The problem is that the auto-generated value A.recordId
is not available within the transaction, unless I make an explicit call of em.flush()
after calling em.persist()
on A
. (If I have an auto-generated IDENTITY PK then the value is directly updated in the entity, but that's not the case here.)
现在我得到了以下两个实体的场景A
和B
(一对一的关系,但不是由 JPA 强制执行或建模的)。A
有一个复合 PK,它是手动设置的,还有一个自动生成的 IDENTITY 字段recordId
。这recordId
应该B
作为外键写入实体A
。我正在保存A
并B
在单笔交易中。问题是自动生成的价值A.recordId
是不可用的事务中,除非我做的一个显式调用em.flush()
打完电话后em.persist()
上A
。(如果我有一个自动生成的 IDENTITY PK,那么该值会直接在实体中更新,但这里不是这种情况。)
Can em.flush()
cause any harm when using it within a transaction?
可以em.flush()
在一个事务中使用时造成什么伤害?
采纳答案by Flavio
Probably the exact details of em.flush()
are implementation-dependent.
In general anyway, JPA providers like Hibernate can cache the SQL instructions they are supposed to send to the database, often until you actually commit the transaction.
For example, you call em.persist()
, Hibernate remembers it has to make a database INSERT, but does not actually execute the instruction until you commit the transaction. Afaik, this is mainly done for performance reasons.
可能的确切细节em.flush()
取决于实现。总的来说,像 Hibernate 这样的 JPA 提供程序可以缓存它们应该发送到数据库的 SQL 指令,通常直到您实际提交事务。例如,您调用em.persist()
,Hibernate 记得它必须进行数据库 INSERT,但在您提交事务之前不会实际执行该指令。Afaik,这主要是出于性能原因。
In some cases anyway you want the SQL instructions to be executed immediately; generally when you need the result of some side effects, like an autogenerated key, or a database trigger.
在某些情况下,您希望立即执行 SQL 指令;通常当您需要某些副作用的结果时,例如自动生成的密钥或数据库触发器。
What em.flush()
does is to empty the internal SQL instructions cache, and execute it immediately to the database.
什么em.flush()
确实是空的内部SQL指令高速缓存,并立即执行到数据库。
Bottom line: no harm is done, only you could have a (minor) performance hit since you are overriding the JPA provider decisions as regards the best timing to send SQL instructions to the database.
底线:没有造成任何伤害,只有您可能会受到(轻微)性能影响,因为您正在覆盖 JPA 提供程序关于将 SQL 指令发送到数据库的最佳时机的决定。
回答by Ricardo Nakashima
Actually, em.flush()
, do more than just sends the cached SQL commands. It tries to synchronize the persistence context to the underlying database. It can cause a lot of time consumption on your processes if your cache contains collections to be synchronized.
实际上,em.flush()
做的不仅仅是发送缓存的 SQL 命令。它尝试将持久性上下文同步到底层数据库。如果您的缓存包含要同步的集合,则可能会导致您的进程消耗大量时间。
Caution on using it.
谨慎使用。
回答by Gab
Can em.flush() cause any harm when using it within a transaction?
在事务中使用 em.flush() 会造成任何伤害吗?
Yes, it may hold locks in the database for a longer duration than necessary.
是的,它可能会在数据库中锁定比必要时间更长的时间。
Generally, When using JPA you delegates the transaction management to the container (a.k.a CMT - using @Transactional annotation on business methods) which means that a transaction is automatically started when entering the method and commited / rolled back at the end. If you let the EntityManager handle the database synchronization, sql statements execution will be only triggered just before the commit, leading to short lived locks in database. Otherwise your manually flushed write operations may retain locks between the manual flush and the automatic commit which can be long according to remaining method execution time.
通常,当使用 JPA 时,您将事务管理委托给容器(又名 CMT - 在业务方法上使用 @Transactional 注释),这意味着事务在进入方法时自动启动并在最后提交/回滚。如果让 EntityManager 处理数据库同步,sql 语句的执行只会在提交前触发,从而导致数据库中的短暂锁定。否则,您手动刷新的写入操作可能会在手动刷新和自动提交之间保留锁定,根据剩余的方法执行时间,这可能会很长。
Notes that some operation automatically triggers a flush : executing a native query against the same session (EM state must be flushed to be reachable by the SQL query), inserting entities using native generated id (generated by the database, so the insert statement must be triggered thus the EM is able to retrieve the generated id and properly manage relationships)
请注意,某些操作会自动触发刷新:对同一会话执行本机查询(必须刷新 EM 状态才能被 SQL 查询访问),使用本机生成的 id(由数据库生成,因此插入语句必须是触发,因此 EM 能够检索生成的 id 并正确管理关系)