10.10. Session 刷出(flush)

优质
小牛编辑
125浏览
2023-12-01

每间隔一段时间,Session 会执行一些必需的 SQL 语句来把内存中的对象的状态同步到 JDBC 连接中。这个过程被称为刷出(flush),默认会在下面的时间点执行:

  • 在某些查询执行之前

  • 在调用 org.hibernate.Transaction.commit() 的时候

  • 在调用 Session.flush() 的时候

涉及的 SQL 语句会按照下面的顺序发出执行:

  1. 所有对实体进行插入的语句,其顺序按照对象执行 Session.save() 的时间顺序

  2. 所有对实体进行更新的语句

  3. 所有进行集合删除的语句

  4. 所有对集合元素进行删除,更新或者插入的语句

  5. 所有进行集合插入的语句

  6. 所有对实体进行删除的语句,其顺序按照对象执行 Session.delete() 的时间顺序

有一个例外是,如果对象使用 native 方式来生成 ID(持久化标识)的话,它们一执行 save 就会被插入。

除非你明确地发出了 flush() 指令,关于 Session 何时会执行这些 JDBC 调用是完全无法保证的,只能保证它们执行的前后顺序。当然,Hibernate 保证,Query.list(..) 绝对不会返回已经失效的数据,也不会返回错误数据。

It is possible to change the default behavior so that flush occurs less frequently. The FlushMode class defines three different modes: only flush at commit time when the Hibernate Transaction API is used, flush automatically using the explained routine, or never flush unless flush() is called explicitly. The last mode is useful for long running units of work, where a Session is kept open and disconnected for a long time (see 第 12.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();

During flush, an exception might occur (e.g. if a DML operation violates a constraint). Since handling exceptions involves some understanding of Hibernate's transactional behavior, we discuss it in 第 12 章 事务和并发 .