如果设置了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时)
这没有说任何有关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。现在,会话从连接池获取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。)
查看以下代码,该代码无事务边界地访问数据库:
Session session = sessionFactory.openSession(); session.get(Item.class, 123l); session.close();
默认情况下,在具有JDBC配置的Java SE环境中,如果执行以下代码片段,将发生以下情况:
该问题的答案是:“取决于情况!” 当在连接上调用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。)
底线:使用显式事务划分。