Java 关于 Hibernate session.flush() 的问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3274958/
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
Question about Hibernate session.flush()
提问by Mahmoud Saleh
I want to inquire about what actually the flush method does in the following case:
我想询问flush方法在以下情况下实际上做了什么:
for (int i = 0; i < myList.size(); i++) {
Car c = new Car( car.get(i).getId(),car.get(i).getName() );
getCurrentSession().save(c);
if (i % 20 == 0)
getCurrentSession().flush();
}
Does this means that after the iteration 20, the cache is flushed, and then the 20 held memory objects are actually saved in the database ?
这是否意味着在迭代 20 次后,刷新缓存,然后将 20 个持有的内存对象实际保存在数据库中?
Can someone please explain to me what will happen when the condition is true.
有人可以向我解释当条件为真时会发生什么。
采纳答案by Pascal Thivent
From the javadoc of Session#flush
:
来自 的javadoc Session#flush
:
Force this session to flush. Must be called at the end of a unit of work, before committing the transaction and closing the session (depending on flush-mode, Transaction.commit()calls this method).
Flushingis the process of synchronizing the underlying persistent store with persistable state held in memory.
强制此会话刷新。必须在工作单元结束时调用,在提交事务和关闭会话之前(取决于 刷新模式,Transaction.commit()调用此方法)。
刷新是将底层持久存储与保存在内存中的持久状态同步的过程。
In other words, flush
tells Hibernate to execute the SQL statements needed to synchronize the JDBC connection's state with the state of objects held in the session-level cache. And the condition if (i % 20 == 0)
will make it happen for every i
multiple of 20.
换句话说,flush
告诉 Hibernate 执行将 JDBC 连接的状态与会话级缓存中保存的对象状态同步所需的 SQL 语句。并且条件if (i % 20 == 0)
将使它发生在每i
20 的倍数上。
But, still, the new Car
instances will be held in the session-level cache and, for big myList.size()
, you're going to eat all memory and ultimately get an OutOfMemoryException
. To avoid this situation, the pattern described in the documentation is to flush
ANDclear
the session at regular intervals (same size as the JDBC batch size) to persist the changes and then detach the instances so that they can be garbage collected:
但是,尽管如此,新Car
实例仍将保存在会话级缓存中,对于 big 而言myList.size()
,您将吃掉所有内存并最终获得OutOfMemoryException
. 为避免这种情况,文档中描述的模式是定期(与 JDBC 批处理大小相同)对会话进行flush
ANDclear
以持久化更改,然后分离实例,以便它们可以被垃圾收集:
13.1. Batch inserts
When making new objects persistent flush() and then clear() the session regularly in order to control the size of the first-level cache.
Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); for ( int i=0; i<100000; i++ ) { Customer customer = new Customer(.....); session.save(customer); if ( i % 20 == 0 ) { //20, same as the JDBC batch size //flush a batch of inserts and release memory: session.flush(); session.clear(); } } tx.commit(); session.close();
13.1. 批量插入
当使新对象持久化时,flush() 然后 clear() 定期会话以控制一级缓存的大小。
Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); for ( int i=0; i<100000; i++ ) { Customer customer = new Customer(.....); session.save(customer); if ( i % 20 == 0 ) { //20, same as the JDBC batch size //flush a batch of inserts and release memory: session.flush(); session.clear(); } } tx.commit(); session.close();
The documentation mentions in the same chapter how to set the JDBC batch size.
文档在同一章中提到了如何设置 JDBC 批处理大小。
See also
也可以看看
回答by Mahmoud Saleh
Yes every 20 loop, sql is generated and executed for the unsaved objects. Your should also set batch mode to 20 to increase performances.
是的,每 20 个循环,就会为未保存的对象生成和执行 sql。您还应该将批处理模式设置为 20 以提高性能。
回答by Manish Singh
// Assume List to be of 50
for (int i = 0; i < 50 ; i++) {
Car c = new Car( car.get(i).getId(),car.get(i).getName() );
getCurrentSession().save(c);
// 20 car Objects which are saved in memory syncronizes with DB
if (i % 20 == 0)
getCurrentSession().flush();
}
Few more pointers regarding why the flushing should match batch size To enable batching you need to set the jdbc batch size
关于为什么刷新应该匹配批处理大小的更多指针要启用批处理,您需要设置 jdbc 批处理大小
// In your case
hibernate.jdbc.batch_size =20
One common pitfall in using batching is if you are using single object update or insert this goes fine.But in case you are using mutiple objects leading to multiple inserts /updates then you will have to explicitly set the sorting mechanism.
使用批处理的一个常见陷阱是,如果您使用单个对象更新或插入,这会很好。但如果您使用多个对象导致多个插入/更新,那么您将必须明确设置排序机制。
For example
例如
// Assume List to be of 50
for (int i = 0; i < 50 ; i++) {
Car c = new Car( car.get(i).getId(),car.get(i).getName() );
// Adding accessory also in the card here
Accessories a=new Accessories("I am new one");
c.add(a);
// Now you got two entities to be persisted . car and accessory
// Two SQL inserts
getCurrentSession().save(c);
// 20 car Objects which are saved in memory syncronizes with DB
// Flush here clears the car objects from 1st level JVM cache
if (i % 20 == 0)
getCurrentSession().flush();
getCurrentSession().clear();
}
Here in this case two sql are generated 1 for insert in car 1 for insert in accessory
在这种情况下,这里生成了两个 sql 1 用于插入汽车 1 用于插入附件
For proper batching you will have to set the
为了正确的批处理,您必须设置
<prop key="hibernate.order_inserts">true</prop>
so that all the inserts for car is sorted together and all inserts of accessories are sorted together.By doing so you will have 20 inserts firing in a batch rather then 1 sql firing at a time.
这样所有的汽车插件都被分类在一起,所有的配件插件也被分类在一起。通过这样做,你将有 20 个插件批量触发,而不是一次触发 1 个 sql。
For different operation under one transaction, you can have a look at http://docs.jboss.org/hibernate/core/3.2/api/org/hibernate/event/def/AbstractFlushingEventListener.html
一个事务下的不同操作,可以查看http://docs.jboss.org/hibernate/core/3.2/api/org/hibernate/event/def/AbstractFlushingEventListener.html
回答by frictionlesspulley
Depends on how the FlushMode is set up.
取决于 FlushMode 的设置方式。
In default configuration Hibernate tries to sync up with the database at three locations.
在默认配置中,Hibernate 尝试在三个位置与数据库同步。
1. before querying data
2. on commiting a transaction
3. explictly calling flush
If the FlushMode
is set as FlushMode.Manual, the programmer is informing hibernate that he/she will handle when to pass the data to the database.Under this configuration
the session.flush()
call will save the object instances to the database.
如果FlushMode
设置为 FlushMode.Manual,则程序员通知 hibernate 他/她将处理何时将数据传递到数据库。在此配置下,session.flush()
调用会将对象实例保存到数据库。
A session.clear()
call acutally can be used to clear the persistance context.
一个session.clear()
调用实际上可以用来清除持久化上下文。