You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

事务回滚会终止Session吗?Hibernate代码报错求助

Hibernate事务、Flush与Rollback详解 + 你的代码异常分析

Hey there! Let's break down your Hibernate question step by step—covering the exception you hit, how rollback works when you flush but don't commit, and a line-by-line deep dive into your code.

一、Flush后未Commit时,Rollback的工作机制

First, let's clarify a few core Hibernate concepts to set the stage:

  • Session的持久化上下文: Hibernate的Session相当于一个内存缓存,你通过Session保存、加载或修改的实体对象都会被"托管"——Hibernate会跟踪所有对这些对象的变更。
  • session.flush(): 这个方法会把Session缓存中所有待处理的变更(比如save()、update()、delete()的操作)同步到数据库。关键是:这只是把SQL语句发送到数据库执行,但这些变更仍处于未提交的事务中,其他事务看不到这些变更,数据也不会永久写入磁盘。
  • transaction.rollback(): 当你调用这个方法时,会发生两件关键的事:
    1. 数据库层面回滚: 数据库会撤销当前事务中所有未提交的变更(也就是你通过flush发送到数据库的那些INSERT操作会被彻底清除,数据库回到事务开始前的状态)。
    2. Session清理: 默认情况下,Hibernate在事务回滚(或提交)后会关闭对应的Session。因为Session是绑定到单个事务生命周期的——一旦事务结束,这个Session就不再具备可用性。

二、你的代码为什么抛出Session is closed异常?

我们逐行拆解你的代码,定位问题根源:

Transaction tr1 = session.beginTransaction(); 
session.save(c1); // 将c1加入Session缓存,标记为待执行INSERT
session.save(c2); // c2同理
c3.setCustName("Robby"); 
session.save(c3); // c3加入缓存,标记为待执行INSERT
session.flush(); // 把c1、c2、c3的INSERT语句发送到数据库,但事务未提交!
tr1.rollback(); // 1. 数据库回滚这3条INSERT;2. Hibernate自动关闭Session
session.save(c4); // 爆炸!Session已经被关闭,调用任何方法都会抛出IllegalStateException
session.save(c5); // 因为前面的异常,这行代码根本不会执行
tr1.commit(); // 同样不会执行,而且tr1已经完成回滚,事务状态早已结束

这里的核心原因是默认情况下回滚会关闭Session。一旦Session关闭,你就不能再对它执行任何操作(比如save()),这就是你看到那个异常的直接原因。

如果需要在回滚后继续操作,该怎么做?

如果你想在回滚后执行新的数据库操作,需要重新打开一个全新的Session,而不是复用已经失效的旧Session:

Transaction tr1 = session.beginTransaction(); 
session.save(c1); 
session.save(c2); 
c3.setCustName("Robby"); 
session.save(c3); 
session.flush(); 
tr1.rollback(); 
session.close(); // 显式关闭已失效的旧Session

// 打开新Session执行后续操作
Session newSession = sessionFactory.openSession();
Transaction tr2 = newSession.beginTransaction();
newSession.save(c4);
newSession.save(c5);
tr2.commit();
newSession.close();

三、给Hibernate新手的小提示

  • Session的生命周期应该很短,绑定单个事务周期(提交或回滚)。事务结束后不要尝试复用Session,直接丢弃即可。
  • flush()的作用是把变更同步到数据库(临时、未提交状态);commit()才会让变更永久写入磁盘,并且对其他事务可见。
  • 回滚不仅会撤销数据库的变更,还会清空Session的缓存并默认关闭Session。

内容的提问来源于stack exchange,提问作者konark

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:01:41