org.hibernate.TransactionException: nested transactions not supported错误的解决方案

本文探讨了Hibernate框架中遇到的nestedtransactionsnotsupported异常原因,并提供了两种解决方案:一是避免嵌套事务,二是规范地手动管理事务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

异常名称: org.hibernate.TransactionException: nested transactions not supported

异常分析You probably have begun a transaction, and trying to begin another one without having committed or rollbacked the previous one.(from stackoverflow.com)

简单得说就是在使用Hbernate框架时,在开启新的transaction时,原来的transaction事务却没有提交或者撤销,导致出现该异常。 我在这里加上一种情况,提交Transaction事务与开启的不一致![/size]


解决方案:第一种:就如大多数偷懒的做法,主动提交事务,去掉以下两行代码。 

session.beginTransation(); 
session.getTransaction().commit();

 

例如:  

public void addUser(User user){
Session session = HibernateUtil.getSession();  
try { 
   session.save(user);  
} catch (Exception e) {  
    e.printStackTrace(); 
   }
}

 
其实Hibernate本身是不具备Transaction处理功能的,Hibernate的Transaction实际上是底层的JDBC Transaction的封装,或者是JTA Transaction的封装。 

#hibernate.transaction.factory_class net.sf.hibernate.transaction.JTATransactionFactory
#hibernate.transaction.factory_class net.sf.hibernate.transaction.JDBCTransactionFactory

 

如果你什么都不配置,默认情况下使用JDBCTransaction。

可以看Hibernate中关于JDBCTransactionFactory的部分

 

package org.hibernate.engine.transaction.internal.jdbc;

public class JdbcTransaction extends AbstractTransactionImpl {
   @Override
   protected void doBegin() {
       ...
       if ( wasInitiallyAutoCommit ) { 
           managedConnection.setAutoCommit( false );
       }
       ...
    }
}

 


转换到Transaction事务处理:当我们什么都不做时,直接使用save()方法(对于所有CURD操作试用), Hibernate使用的是session.setAutoCommit(true),对应到JDBC,就是connection.setAutoCommit(true);数据库就帮你给把事务代理了。

但一旦使用session.beginTransation()或者session.getTransation().begin(), Hibernate 将自动提交事物关闭:session.setAutoCommit(false),这是必须手动提交事务。


所以就引申出第二种解决方案:手动提交事务

在有自动提交事务的情况下,为什么要手动提交事务呢?主要是针对以后的高并发问题,手动提交事务可以更有效的控制高并发可能出现的各种问题。


其实,大多数是手动提交事务,但是代码写的不准确,比如说我。下面是不规范的代码

 

public void addUser(User user){  //错误代码
   Session session = HibernateUtil.getSession(); 
   session.beginTransaction(); 
   try { 
      session.save(user); 
      session.getTransaction().commit();
   } catch (Exception ef) {  
       ef.printStackTrace();  
   }
}

 

规范的写法是下面这种:保证是同一个事务。

 
]public void addUser(User user){  //正确写法
   Session session = HibernatUtil.getSession(); 
   Transaction tx = session.beginTransaction(); 
   try { 
      session.save(user); 
      tx.commit(); //事物必须提交
   } catch (Exception ef) { 
      if (null != tx) {
         tx.rollback();//撤销事务
         ef.printStackTrace(); 
      }
   }
}
 
### 解决方案 当遇到 `org.hibernate.TransactionException: JDBC begin transaction failed` 错误时,这通常意味着在尝试启动事务之前,JDBC 连接已经出现问题。此问题可能由多种因素引起,包括但不限于配置不正确、资源不可用或网络中断。 #### 配置检查 确保应用程序中的 Hibernate 和数据源配置文件设置无误。特别是要确认数据库方言 (`hibernate.dialect`) 已经被正确定义[^1]: ```properties spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect ``` 如果未指定该属性,则可能会抛出异常 `Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set`. #### 使用连接池优化性能并提高稳定性 引入合适的数据库连接池可以有效缓解因频繁建立新连接而导致的问题。常见的开源解决方案有 HikariCP 或者 Apache Commons DBCP 等工具[^2]。以下是基于 Spring Boot 应用程序的一个简单例子来集成HikariCP: ```yaml spring: datasource: type: com.zaxxer.hikari.HikariDataSource hikari: maximumPoolSize: 10 minimumIdle: 5 idleTimeout: 30000 connectionTestQuery: SELECT 1 FROM DUAL ``` 通过上述方式调整最大/最小空闲连接数以及超时时间参数可以帮助维持稳定的连接状态,并减少由于瞬态故障引发的错误几率。 #### 日志记录与监控 增强日志级别以便更好地追踪潜在问题所在位置。对于生产环境而言,建议启用详细的 SQL 执行日志输出,这样可以在发生异常时快速定位根源。 ```java logging.level.org.springframework.transaction=DEBUG logging.level.org.hibernate.SQL=DEBUG ``` 此外,考虑部署专业的 APM(Application Performance Management) 平台用于实时监测应用表现情况,及时发现并处理可能出现的服务降级事件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值