我想询问以下情况下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();
}
这是否意味着在迭代20之后,刷新缓存,然后20个持有的内存对象实际上保存在数据库中?
有人可以向我解释当条件成立时会发生什么。
答案 0 :(得分:51)
来自Session#flush
的javadoc:
强制此会话刷新。一定是 在工作单元结束时调用, 在提交交易之前 结束会议(取决于 flush-mode,Transaction.commit() 称这种方法。)
刷新是同步底层的过程 具有持久性的持久存储 国家在记忆中举行。
换句话说,flush
告诉Hibernate执行将JDBC连接状态与会话级缓存中保存的对象状态同步所需的SQL语句。条件if (i % 20 == 0)
将使每个i
的倍数达到20。
但是,新的Car
实例仍将保留在会话级缓存中,对于大myList.size()
,您将占用所有内存并最终得到{{1} }。为了避免这种情况,文档中描述的模式是OutOfMemoryException
AND flush
会话定期(与JDBC批处理大小相同)以保持更改和然后分离实例,以便它们可以被垃圾收集:
13.1. Batch inserts
使新对象持久化 flush()然后清除()会话 定期以控制大小 第一级缓存。
clear
文档在同一章中提到了如何设置JDBC批量大小。
答案 1 :(得分:2)
取决于如何设置FlushMode。
在默认配置中,Hibernate尝试在三个位置与数据库同步。
1. before querying data
2. on commiting a transaction
3. explictly calling flush
如果将FlushMode
设置为FlushMode.Manual,则程序员通知hibernate他/她将处理何时将数据传递到数据库。在此配置下
session.flush()
调用会将对象实例保存到数据库中。
可以使用session.clear()
实际调用来清除持久性上下文。
答案 2 :(得分:1)
// 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();
}
关于为什么冲洗应该与批量大小匹配的更多指示 要启用批处理,您需要设置jdbc批处理大小
// In your case
hibernate.jdbc.batch_size =20
使用批处理的一个常见缺陷是,如果您使用单个对象更新或插入,这很好。但以防万一 你正在使用导致多次插入/更新的多个对象,那么你必须明确地设置排序机制。
例如
// 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();
}
在这种情况下 生成两个sql 1用于插入汽车 1用于插入配件
要进行正确的批处理,您必须设置
<prop key="hibernate.order_inserts">true</prop>
这样汽车的所有插件都被整理在一起,并且所有附件插件都被分类在一起。通过这样做,你将有20个插件批量发射,而不是一次发射1个sql。
对于一次交易下的不同操作,您可以查看http://docs.jboss.org/hibernate/core/3.2/api/org/hibernate/event/def/AbstractFlushingEventListener.html
答案 3 :(得分:0)
是每20个循环,为未保存的对象生成并执行sql。您还应将批处理模式设置为20以提高性能。