10.10. Session刷出(flush)
每间隔一段时间,Session
会执行一些必需的SQL语句来把内存中的对象的状态同步到JDBC连接中。这个过程被称为刷出(flush),默认会在下面的时间点执行:
在某些查询执行之前
在调用
org.hibernate.Transaction.commit()
的时候在调用
Session.flush()
的时候
涉及的SQL语句会按照下面的顺序发出执行:
所有对实体进行插入的语句,其顺序按照对象执行
Session.save()
的时间顺序所有对实体进行更新的语句
所有进行集合删除的语句
所有对集合元素进行删除,更新或者插入的语句
所有进行集合插入的语句
所有对实体进行删除的语句,其顺序按照对象执行
Session.delete()
的时间顺序
(有一个例外是,如果对象使用native
方式来生成ID(持久化标识)的话,它们一执行save就会被插入。)
除非你明确地发出了flush()
指令,关于Session何时会执行这些JDBC调用是完全无法保证的,只能保证它们执行的前后顺序。 当然,Hibernate保证,Query.list(..)
绝对不会返回已经失效的数据,也不会返回错误数据。
也可以改变默认的设置,来让刷出(flush)操作发生的不那么频繁。 FlushMode
类定义了三种不同的方式。 仅在提交时刷出(仅当Hibernate的Transaction
API被使用时有效), 按照刚才说的方式刷出, 以及除非明确使用flush()
否则从不刷出。 最后一种模式对于那些需要长时间保持Session
为打开或者断线状态的长时间运行的工作单元很有用。 (参见 第 11.3.2 节 “扩展周期的session和自动版本化”).
sess = sf.openSession();
Transaction tx = sess.beginTransaction();
sess.setFlushMode(FlushMode.COMMIT); // allow queries to return stale state
Cat izi = (Cat) sess.load(Cat.class, id);
izi.setName(iznizi);
// might return stale data
sess.find("from Cat as cat left outer join cat.kittens kitten");
// change to izi is not flushed!
...
tx.commit(); // flush occurs
sess.close();
刷出(flush)期间,可能会抛出异常。(例如一个DML操作违反了约束) 异常处理涉及到对Hibernate事务性行为的理解,因此我们将在第 11 章 事务和并发中讨论。