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

Itt*_*tai 5 java session hibernate flush

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

我知道session.close()通常不会刷新会话但我不确定FlushMode.AUTO如何影响这个.

来自Docs:

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

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

小代码示例:

Session session = HibernateSessionFactory.getSession();  
PersistedObject p = session.get(PersistedObject.class,id);  
p.setSomeProperty(newValue);  
session.close();
Run Code Online (Sandbox Code Playgroud)

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

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

这没有说明Session.close()

Pas*_*ent 13

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

不,它不会,你应该使用具有明确界限的交易.引用非事务性数据访问和自动提交模式:

与Hibernate非交易地工作

查看以下代码,该代码访问没有事务边界的数据库:

Session session = sessionFactory.openSession(); 
session.get(Item.class, 123l); 
session.close(); 
Run Code Online (Sandbox Code Playgroud)

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

  1. 将打开一个新会话.此时它不会获得数据库连接.
  2. 对get()的调用会触发SQL SELECT.Session现在从连接池获取JDBC连接.默认情况下,Hibernate会立即使用setAutoCommit(false)关闭此连接上的自动提交模式.这有效地启动了JDBC事务!
  3. SELECT在此JDBC事务中执行.会话关闭,连接返回到池并由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(); 
Run Code Online (Sandbox Code Playgroud)

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

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