Hibernate: ush()和 commit()

单独调用 org.hibernate.Session.flush()是一种好的做法吗?

正如 org.hibernate.Session文档中所说,

必须在工作单元结束时调用,然后提交事务并关闭会话(取决于刷新模式,Transaction.commit ()调用此方法)。

如果 org.hibernate.Transaction.commit()已经这样做了,你能明确地解释调用 flush()的目的吗?

188963 次浏览

In the Hibernate Manual you can see this example

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();

Without the call to the flush method, your first-level cache would throw an OutOfMemoryException

Also you can look at this post about flushing

By default flush mode is AUTO which means that: "The Session is sometimes flushed before query execution in order to ensure that queries never return stale state", but most of the time session is flushed when you commit your changes. Manual calling of the flush method is usefull when you use FlushMode=MANUAL or you want to do some kind of optimization. But I have never done this so I can't give you practical advice.

One common case for explicitly flushing is when you create a new persistent entity and you want it to have an artificial primary key generated and assigned to it, so that you can use it later on in the same transaction. In that case calling flush would result in your entity being given an id.

Another case is if there are a lot of things in the 1st-level cache and you'd like to clear it out periodically (in order to reduce the amount of memory used by the cache) but you still want to commit the whole thing together. This is the case that Aleksei's answer covers.

flush(); Flushing is the process of synchronizing the underlying persistent store with persistable state held in memory. It will update or insert into your tables in the running transaction, but it may not commit those changes.

You need to flush in batch processing otherwise it may give OutOfMemoryException.

Commit(); Commit will make the database commit. When you have a persisted object and you change a value on it, it becomes dirty and hibernate needs to flush these changes to your persistence layer. So, you should commit but it also ends the unit of work (transaction.commit()).

flush() will synchronize your database with the current state of object/objects held in the memory but it does not commit the transaction. So, if you get any exception after flush() is called, then the transaction will be rolled back. You can synchronize your database with small chunks of data using flush() instead of committing a large data at once using commit() and face the risk of getting an OutOfMemoryException.

commit() will make data stored in the database permanent. There is no way you can rollback your transaction once the commit() succeeds.

session.flush() is synchronise method means to insert data in to database sequentially.if we use this method data will not store in database but it will store in cache,if any exception will rise in middle we can handle it. But commit() it will store data in database,if we are storing more amount of data then ,there may be chance to get out Of Memory Exception,As like in JDBC program in Save point topic

It is usually not recommended to call flush explicitly unless it is necessary. Hibernate usually auto calls Flush at the end of the transaction and we should let it do it's work. Now, there are some cases where you might need to explicitly call flush where a second task depends upon the result of the first Persistence task, both being inside the same transaction.

For example, you might need to persist a new Entity and then use the Id of that Entity to do some other task inside the same transaction, on that case it's required to explicitly flush the entity first.

@Transactional
void someServiceMethod(Entity entity){
em.persist(entity);
em.flush() //need to explicitly flush in order to use id in next statement
doSomeThingElse(entity.getId());
}

Also Note that, explicitly flushing does not cause a database commit, a database commit is done only at the end of a transaction, so if any Runtime error occurs after calling flush the changes would still Rollback.