Search code examples
javahibernatetransactionshibernate-session

Hibernate - Could not obtain transaction-synchronized Session for current thread


I understand this question has been asked many time, but most can't explain my problem:

@RequestMapping("/testing")
public String testing(HttpServletRequest request, final ModelMap model) 
{
    Transaction ut = session.openSession().beginTransaction();

    session.getCurrentSession(); // error here

    ut.commit();

    return "testing";
}

Why I am getting the error

Could not obtain transaction-synchronized Session for current thread.

If I annotate the method with @Transactional, it is working perfectly fine. Because I have @EnableTransactionManagement in my spring context.

I want to try something to understand the difference between getCurrentSessionand openSession, so I created test case above.

getCurrentSession is called within a active Transaction context, why it is still throwing me error???

Refer the code from this.


Solution

  • OK, after so long time of research, I found out I have miss out the paragraph below:

    You will not see these code snippets in a regular application; fatal (system) exceptions should always be caught at the "top". In other words, the code that executes Hibernate calls in the persistence layer, and the code that handles RuntimeException (and usually can only clean up and exit), are in different layers. The current context management by Hibernate can significantly simplify this design by accessing a SessionFactory. Exception handling is discussed later in this chapter.

    So the example showing there indeed will not be working in regular scenario...

    I have to do as below:

    // BMT idiom with getCurrentSession()
    try {
        UserTransaction tx = (UserTransaction)new InitialContext()
                                .lookup("java:comp/UserTransaction");
    
        tx.begin();
    
        // Do some work on Session bound to transaction
        factory.getCurrentSession().load(...);
        factory.getCurrentSession().persist(...);
    
        tx.commit();
    }
    catch (RuntimeException e) {
        tx.rollback();
        throw e; // or display error message
    }
    

    Which mean, the usage of getCurrentSession is pretty restricted, it must be running in a active (and specific) transaction.