6

如果设置了 FlushMode.AUTO,当我调用 session.close() 时,Hibernate 会刷新我更新的持久对象吗?

我知道 session.close() 通常不会刷新会话,但我不确定 FlushMode.AUTO 对此有何影响。

从文档:

FlushMode.AUTO
有时会在查询执行之前刷新会话,以确保查询永远不会返回过时状态。这是默认的刷新模式。

这是否意味着我可以依靠 Hibernate 来验证我的更改有时会在我的会话关闭之前被刷新?

小代码示例:

Session session = HibernateSessionFactory.getSession();  
PersistedObject p = session.get(PersistedObject.class,id);  
p.setSomeProperty(newValue);  
session.close();

更新
根据文档,这些是会话刷新的地方(使用 AUTO 时)

  • 在一些查询执行之前
  • 来自 org.hibernate.Transaction.commit()
  • 从 Session.flush()

这并没有说明 Session.close()

4

2 回答 2

14

调用 session.close()(使用 FlushMode.AUTO)时,Hibernate 会刷新我更新的持久对象吗?

不,不会,您应该使用边界明确的事务。引用非事务性数据访问和自动提交模式

使用 Hibernate 以非事务方式工作

看下面的代码,它在没有事务边界的情况下访问数据库:

Session session = sessionFactory.openSession(); 
session.get(Item.class, 123l); 
session.close(); 

默认情况下,在具有 JDBC 配置的 Java SE 环境中,如果您执行以下代码段会发生以下情况:

  1. 一个新的会话被打开。此时它没有获得数据库连接。
  2. 对 get() 的调用会触发 SQL SELECT。Session 现在从连接池中获得一个 JDBC Connection。默认情况下,Hibernate 会立即使用 setAutoCommit(false) 关闭此连接上的自动提交模式。这有效地启动了一个 JDBC 事务!
  3. SELECT 在这个 JDBC 事务中执行。会话关闭,连接返回池并由 Hibernate 释放 - Hibernate 调用 JDBC Connection 上的 close()。未提交的事务会发生什么?

这个问题的答案是,“这取决于!” 当在连接上调用 close() 时,JDBC 规范没有说明待处理的事务。会发生什么取决于供应商如何实施规范。例如,对于 Oracle JDBC 驱动程序,对 close() 的调用会提交事务!大多数其他 JDBC 供应商采取理智的方式,并在 JDBC Connection 对象关闭并将资源返回到池时回滚任何待处理的事务。

显然,这对于您执行的 SELECT 来说不是问题,但是看看这个变体:

Session session = getSessionFactory().openSession(); 
Long generatedId = session.save(item); 
session.close(); 

此代码生成一个 INSERT 语句,该语句在从未提交或回滚的事务中执行。在 Oracle 上,这段代码永久插入数据;在其他数据库中,它可能不会。(这种情况稍微复杂一些:只有在标识符生成器需要时才执行 INSERT。例如,可以从没有 INSERT 的序列中获取标识符值。然后持久化实体排队等待刷新时间插入——这永远不会发生在此代码中。标识策略需要立即插入以生成值。)

底线:使用明确的事务划分。

于 2010-10-14T09:00:37.640 回答
0

关闭会话将始终将所有工作刷新到数据库。Flushmode.AUTO 在发生更改时将工作刷新到数据库并且您正在使用更改的记录查询表。

于 2010-10-14T08:05:35.793 回答