在使用FlushMode.AUTO调用session.close()时,Hibernate会刷新我更新的持久对象吗?
如果设置了FlushMode.AUTO,当我调用session.close()时,Hibernate会刷新我更新的持久对象吗?
我知道session.close()通常不会刷新会话但我不确定FlushMode.AUTO如何影响这个。
来自Docs:
FlushMode.AUTO
会话有时在查询执行之前刷新,以确保查询永远不会返回失效状态。 这是默认的刷新模式。
这是否意味着我可以依赖Hibernate来validation我的更改有时会在我的会话关闭之前刷新?
小代码示例:
Session session = HibernateSessionFactory.getSession(); PersistedObject p = session.get(PersistedObject.class,id); p.setSomeProperty(newValue); session.close();
UPDATE
根据文档,这些是会话将刷新的地方(使用AUTO时)
- 在一些查询执行之前
- 来自org.hibernate.Transaction.commit()
- 来自Session.flush()
这没有说明Session.close()
在调用session.close()(使用FlushMode.AUTO)时,Hibernate会刷新我更新的持久对象吗?
不,它不会,你应该使用具有明确界限的交易 。 引用非事务性数据访问和自动提交模式 :
与Hibernate非交易地工作
查看以下代码,该代码访问没有事务边界的数据库:
Session session = sessionFactory.openSession(); session.get(Item.class, 123l); session.close();
默认情况下,在具有JDBC配置的Java SE环境中,如果执行此代码段,则会发生以下情况:
- 将打开一个新会话。 此时它不会获得数据库连接。
- 对get()的调用会触发SQL SELECT。 Session现在从连接池获取JDBC连接。 默认情况下,Hibernate会立即使用setAutoCommit(false)关闭此连接上的自动提交模式。 这有效地启动了JDBC事务!
- 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();
此代码生成一个INSERT语句,在从未提交或回滚的事务中执行。 在Oracle上,这段代码永久地插入数据; 在其他数据库中,它可能不会。 (这种情况稍微复杂一点:只有在标识符生成器需要它时才执行INSERT。例如,可以从没有INSERT的序列中获取标识符值。 然后将持久化实体排队,直到刷新时插入 – 从不在此代码中发生 。身份策略需要立即INSERT才能生成值。)
底线:使用显式事务划分。
关闭会话将始终将工作清理到数据库。 当有更改并且您正在使用更改的记录查询表时,Flushmode.AUTO会将工作刷新到数据库。