Hibernate org.hibernate.TransactionException:jaxrs不支持嵌套事务 [英] Hibernate org.hibernate.TransactionException: nested transactions not supported on jaxrs

查看:464
本文介绍了Hibernate org.hibernate.TransactionException:jaxrs不支持嵌套事务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



<问题是,在一些随机的时间间隔我得到org.hibernate.TransactionException:嵌套事务不支持异常,但我不想创建一个新的会话,除了在过滤器。



如果我错了,纠正我,但是当将当前会话类设置为线程时,我不需要在hibernateutil中创建threadlocal,hibernate会执行此操作。所以我的问题是,这是一个安全的方式来处理,并可能导致错误发生在随机间隔?



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



抱歉,不要提前发布代码。
因此过滤器在请求过滤器中实现了ContainerRequestFilter,ContainerResponseFilter



我正在做的事情

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

以及在回复中

  Transaction transaction = sessionfactory.getCurrentSession()。getTransaction(); 
if(transaction!= null&!transaction.wasCommitted()
&&!transaction.wasRolledBack()&& transaction.isActive()) {
transaction.commit();

} catch(HibernateException e){
Transaction transaction = sessionfactory.getCurrentSession()。getTransaction();
if(transaction!= null&& transaction.isActive()){
transaction.rollback();

} catch(HibernateException e){

} finally {
Session session = sessionfactory.getCurrentSession();
if(session!= null&& session.isOpen()){
session.close();

} catch(HibernateException e){
log.error(回滚后关闭会话错误:,e);
throw e;
}

}

解决方案

似乎你正在过滤器中使用编程事务划分(据我了解)。所以请仔细检查你是否正确地终止了每个事务,不要在请求期间追加什么(即回滚,如果你遇到异常并以其他方式提交):

  try {
session.getTransaction()。begin();
//调用过滤器链
session.getTransaction()。commit()
}
catch(RuntimeException e){
session.getTransaction()。rollback );
}

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



编辑



在您的代码中,它可以确认我的假设。



查看 transaction.wasRolledBack()== true :它不会被提交或回滚。



如果你使用 Transaction.wasRolledBack()


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


如果事务被标记为仅回滚:它将返回true,但这并不意味着th e交易结束。这意味着交易的唯一可能的结束状态是RollBack。

但是,另一方面,相同的javadoc也会这样说:


返回:boolean如果事务通过本地事务回滚,则为真;假如不是这样的话。


我发现这个模糊不清。

要做到这一点:

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


I am using jersey with mysql and hibernate 4 and c3p0. I have created a initialization servlet that configures hibernate and sets the current session context class to thread. I have created hibernateUtils class that contains static methods for getting and committing sessions and I am using a filter to start a session on inbound request and commit it upon response.

The problem is that at some random intervals I am getting org.hibernate.TransactionException: nested transactions not supported exception, but I am not trying to create a new session except on the filter.

Correct me if I am wrong but when setting the current session class to thread I don't need to create a threadlocal in the hibernateutil, hibernate does this. So my question is, is this a safe way to handle that and what could cause the error happening on random intervals?

====================== EDIT ===========================

Sorry for not posting the code earlier. So the filter implements the ContainerRequestFilter,ContainerResponseFilter

in the request filter I am doing

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

and in the response

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;
     }

}

解决方案

It seems that you are using programmatic transaction demarcation in your filter (as far as I understood). So please double check that you terminate properly each transaction, nevermind what append during the request (i.e. rollback if you get an exception and commit otherwise) :

try {
    session.getTransaction().begin();
    // call the filter chain
    session.getTransaction().commit()
}
catch (RuntimeException e) {
    session.getTransaction().rollback();
}

Without the code it's difficult to be sure, but I guess that for some request you didn't terminate the transaction properly (i.e. by a commit or by a rollback). So the transaction remains associated to the thread and the thread go back to the thread pool (in a very strange state since there is still a transaction associated with it), then another request reuse the same thread, a new transaction is created in the filter... and you got the exception.

EDIT

After looking carrefully at your code, it (may) confirms my assumptions.

Look at the flow when transaction.wasRolledBack()==true : it won't be commited nor rolled back.

And if you the javadoc for Transaction.wasRolledBack() :

Was this transaction rolled back or set to rollback only?

If the transaction is marked as "RollBack only" : it will return true, but it don't means that the transaction is ended. It means that the only possible ending state for the transaction is "RollBack".

But, on the other hand the same javadoc also say this:

Returns: boolean True if the transaction was rolled back via this local transaction; false otherwise.

I found that ambiguous.

So I suggest you to do this:

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

这篇关于Hibernate org.hibernate.TransactionException:jaxrs不支持嵌套事务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆