Hibernate执行createQuery查询时出现java.lang.IllegalStateException异常
异常触发原因
- 回滚逻辑缺少事务状态校验:当前catch块中只要transaction不为空就直接调用
rollback(),但此时如果try-with-resources已经自动关闭了Session,或者事务已经处于提交/回滚完成的非活跃状态,调用rollback就会抛出连接已关闭的异常,甚至会覆盖原本触发catch的原始异常。 - hibernate配置文件存在冗余错误映射:
hibernate.cfg.xml中添加了DAO类的映射配置<mapping class="ef.uniceplac.users.dao.ProdutosDAO"/>,映射配置只应该用于标注了@Entity的实体类,DAO类不属于实体映射对象,这个错误配置会导致Hibernate初始化阶段产生异常,触发回滚逻辑。 - 非必要事务增加逻辑风险:只读查询不需要显式开启事务,Hibernate的查询操作默认可以在非事务环境下执行,强行增加事务逻辑反而引入不必要的连接占用、状态判断风险。
解决方案
1. 修复DAO层逻辑
优先推荐直接简化只读查询的事务逻辑,修改getTodosProdutos方法如下:
public List <Produtos> getTodosProdutos(){ List <Produtos> listaDeProdutos = null; try(Session session = HibernateUtil.getSessionFactory().openSession()){ // 增加泛型类声明避免类型转换警告 listaDeProdutos = session.createQuery("from Produtos ", Produtos.class).getResultList(); }catch(Exception e) { e.printStackTrace(); } return listaDeProdutos; }
如果需要保留事务写法,必须在回滚前判断事务活跃状态:
public List <Produtos> getTodosProdutos(){ Transaction transaction = null; List <Produtos> listaDeProdutos = null; try(Session session = HibernateUtil.getSessionFactory().openSession()){ transaction = session.beginTransaction(); listaDeProdutos = session.createQuery("from Produtos ", Produtos.class).getResultList(); transaction.commit(); }catch(Exception e) { // 只有事务处于活跃状态时才执行回滚 if(transaction != null && transaction.getStatus().isActive()) { transaction.rollback(); } e.printStackTrace(); } return listaDeProdutos; }
2. 删除hibernate配置文件中的冗余映射
打开hibernate.cfg.xml,删除下面这行错误配置:
<mapping class="ef.uniceplac.users.dao.ProdutosDAO"/>
可选优化
- 如果你使用的是MySQL 8.x版本,可将驱动类配置更新为
<property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>,避免驱动版本兼容警告。 - 长期运行的项目建议添加C3P0等连接池配置,避免数据库连接自动断开导致的异常。
内容的提问来源于stack exchange,提问作者Rubens Júnior
相关产品推荐
相关产品推荐

