当调用session.close()(使用FlushMode.AUTO)时,Hibernate是否会刷新更新的持久对象?
不,它不会,您应该 使用边界明确的事务
。引用非事务数据访问和自动提交模式:
与Hibernate进行非事务处理
查看以下代码,该代码无事务边界地访问数据库:
Session session = sessionFactory.openSession();session.get(Item.class, 123l);session.close();默认情况下,在具有JDBC配置的Java SE环境中,如果执行以下代码片段,将发生以下情况:
- 打开一个新的会话。此时,它尚未获得数据库连接。
- 调用get()会触发SQL
SELECT。现在,会话从连接池获取JDBC连接。默认情况下,Hibernate使用setAutoCommit(false)立即关闭此连接上的自动提交模式。这有效地启动了JDBC事务!- 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。)
底线:使用显式事务划分。



