Hibernate org.hibernate.TransactionException:jaxrs 不支持嵌套事务

Posted

技术标签:

【中文标题】Hibernate org.hibernate.TransactionException:jaxrs 不支持嵌套事务【英文标题】:Hibernate org.hibernate.TransactionException: nested transactions not supported on jaxrs 【发布时间】:2013-09-12 20:08:31 【问题描述】:

我正在使用带有 mysql 和 hibernate 4 和 c3p0 的球衣。我创建了一个初始化 servlet,它配置休眠并将当前会话上下文类设置为线程。 我创建了 hibernateUtils 类,其中包含用于获取和提交会话的静态方法,并且我正在使用过滤器在入站请求上启动会话并在响应时提交它。

问题是,在某些随机时间间隔,我收到 org.hibernate.TransactionException: nested transactions not supported 异常,但我没有尝试在过滤器上创建新会话。

如果我错了,请纠正我,但是在将当前会话类设置为线程时,我不需要在 hibernateutil 中创建 threadlocal,hibernate 会这样做。所以我的问题是,这是一种安全的处理方式吗?什么可能导致随机间隔发生错误?

=======================编辑======================== ===

很抱歉没有早点发布代码。 所以过滤器实现了ContainerRequestFilter,ContainerResponseFilter

在我正在做的请求过滤器中

Session session = sessionfactory.getCurrentSession();
session.getTransaction().begin();
session.setDefaultReadOnly(readOnly);

在响应中

Transaction transaction = sessionfactory.getCurrentSession().getTransaction();
try 
    if (transaction != null && !transaction.wasCommitted()
       && !transaction.wasRolledBack() && transaction.isActive()) 
        transaction.commit();
    
 catch (HibernateException e) 
    Transaction transaction = sessionfactory.getCurrentSession().getTransaction();
    try 
        if (transaction != null && transaction.isActive()) 
            transaction.rollback();
        
     catch (HibernateException e) 

     finally 
         Session session = sessionfactory.getCurrentSession();
         try 
              if (session != null && session.isOpen()) 
                  session.close();
              
          catch (HibernateException e) 
            log.error("Closing session after rollback error: ", e);
            throw e;
     

【问题讨论】:

你能发布错误的堆栈跟踪吗?和你的过滤器代码? 【参考方案1】:

您似乎在过滤器中使用了程序化事务划分(据我了解)。因此,请仔细检查您是否正确终止了每个事务,不要在意请求期间附加的内容(即,如果您遇到异常则回滚,否则提交):

try 
    session.getTransaction().begin();
    // call the filter chain
    session.getTransaction().commit()

catch (RuntimeException e) 
    session.getTransaction().rollback();

没有代码很难确定,但我猜对于某些请求,您没有正确终止事务(即通过提交或回滚)。所以事务仍然与线程关联,线程回到线程池(处于非常奇怪的状态,因为仍然有一个事务与之关联),然后另一个请求重用同一个线程,在过滤器中创建一个新事务...你得到了例外。

编辑

仔细查看您的代码后,它(可能)证实了我的假设。

transaction.wasRolledBack()==true时的流程:不会commit也不会回滚。

如果你是 Transaction.wasRolledBack() 的 javadoc:

此事务是回滚还是设置为仅回滚

如果事务被标记为“仅回滚”:它会返回true,但并不意味着事务结束。这意味着事务唯一可能的结束状态是“回滚”。

但是,另一方面,同一个 javadoc 也这样说:

返回: boolean 如果事务通过此本地事务回滚,则为 True;否则为假。

我发现这个模棱两可。

所以我建议你这样做:

if (transaction != null && !transaction.wasCommitted()
   && !transaction.wasRolledBack() && transaction.isActive()) 
    transaction.commit();
else if(transaction.wasRolledBack())
    transaction.rollback();

【讨论】:

抱歉之前没有发布示例代码,我已经更新了我的问题,我知道看起来是这样,但我想不出泄露的会话可能在哪里,因为我终于要关闭它了! 感谢您的提示,我会尝试看看错误是否仍然存在。

以上是关于Hibernate org.hibernate.TransactionException:jaxrs 不支持嵌套事务的主要内容,如果未能解决你的问题,请参考以下文章

休眠教程不起作用

Hibernate→ 《Hibernate程序开发》教材大纲

hibernate问题

Spring和Hibernate的注解整合 hibernate3和hibernate4/5的区别

hibernate.merge()方法怎么用

hibernate 异常 怎么解决