事务回滚会终止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(): 当你调用这个方法时,会发生两件关键的事:- 数据库层面回滚: 数据库会撤销当前事务中所有未提交的变更(也就是你通过flush发送到数据库的那些
INSERT操作会被彻底清除,数据库回到事务开始前的状态)。 - Session清理: 默认情况下,Hibernate在事务回滚(或提交)后会关闭对应的Session。因为Session是绑定到单个事务生命周期的——一旦事务结束,这个Session就不再具备可用性。
- 数据库层面回滚: 数据库会撤销当前事务中所有未提交的变更(也就是你通过flush发送到数据库的那些
二、你的代码为什么抛出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
相关产品推荐
相关产品推荐

