一尘不染

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

hibernate

如果设置了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()的信息


阅读 272

收藏
2020-06-20

共1个答案

一尘不染

当调用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。现在,会话从连接池获取JDBC连接。默认情况下,Hibernate使用setAutoCommit(false)立即关闭此连接上的自动提交模式。这有效地启动了JDBC事务!
  3. SELECT在此JDBC事务内执行。Session关闭,并且连接返回到池中并由Hibernate释放-Hibernate在JDBC
    Connection上调用close()。未提交的交易会怎样?

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

显然,这对于您执行的SELECT来说不是问题,但请看以下变化:

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

此代码将导致INSERT语句,该语句在从未提交或回滚的事务内执行。在Oracle上,这段代码永久地插入数据。在其他数据库中,可能没有。(这种情况稍微复杂一些:仅在标识符生成器需要时才执行INSERT。例如,可以从没有INSERT的序列中获取标识符值。
然后将持久性实体排队,直到刷新时间插入为止-永远不会发生在这个代码 。一个身份策略需要对将要产生的值立即INSERT。)

底线:使用显式事务划分。

2020-06-20