3

I am getting a

org.hibernate.TransactionException: nested transactions not supported
at    org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:152)
at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1395)
at com.mcruiseon.server.hibernate.ReadOnlyOperations.flush(ReadOnlyOperations.java:118)

Code that throws that exception. I am calling flush from a thread that runs infinite until there is data to flush.

public void flush(Object dataStore) throws DidNotSaveRequestSomeRandomError {
    Transaction txD;
    Session session;
    session = currentSession();
    // Below Line 118 
    txD = session.beginTransaction();
    txD.begin() ;
    session.saveOrUpdate(dataStore);
    try {
        txD.commit();
        while(!txD.wasCommitted()) ;
    } catch (ConstraintViolationException e) {
        txD.rollback() ;
        throw new DidNotSaveRequestSomeRandomError(dataStore, feedbackManager);
    } catch (TransactionException e) {
        txD.rollback() ;
    }  finally {
        // session.flush();
        txD = null;
        session.close();
    }
    // mySession.clear();
}

Edit : I am calling flush in a independent thread as datastore list contains data. From what I see its a sync operation call to flush, so ideally flush should not return until transaction is complete. I would like it that way is the least I want to expect. Since its a independent thread doing its job, all I care about it flush being a sync operation. Now my question is, is txD.commit a async operation ? Does it return before that transaction has a chance to finish. If yes, is there a way to get commit to "Wait" until the transaction completes ?

        public void run() {
        Object dataStore = null;
        while (true) {
            try {
                synchronized (flushQ) {
                    if (flushQ.isEmpty())
                        flushQ.wait();
                    if (flushQ.isEmpty()) {
                        continue;
                    }
                    dataStore = flushQ.removeFirst();
                    if (dataStore == null) {
                        continue;
                    }
                }
                try {
                    flush(dataStore);
                } catch (DidNotSaveRequestSomeRandomError e) {
                    e.printStackTrace();
                    log.fatal(e);
                }
            } catch (HibernateException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

Edit 2 : Added while(!txD.wasCommitted()) ; (in code above), still I get that freaking nested transactions not supported. Infact due to this exception a record is not being written to by table too. Is there something to do with the type of table ? I have INNODB for all my tables?

Siddharth
  • 9,349
  • 16
  • 86
  • 148
  • 1
    I think you are starting transaction twice, can you try removing the second statement `txD = session.beginTransaction(); txD.begin() ;` – Subin Sebastian Jan 07 '13 at 05:20
  • Removed, same result. nested transactions not supported exception. – Siddharth Jan 07 '13 at 05:23
  • 2
    Ok remove both lines and use `session.getTransaction()` to get instance of transaction and let us know. – Subin Sebastian Jan 07 '13 at 05:29
  • Btw, I just read somewhere that the begin creates a new transaction, while getTransation reuses the older one. Try the getTransaction(), will report in a few minutes. – Siddharth Jan 07 '13 at 05:54
  • Thanks, your hints helped me search more and get the appropriate answer. – Siddharth Jan 07 '13 at 06:32
  • Another interesting link I found, worth mentioning so that people coming to this question know what else I found in my research http://www.java2s.com/Questions_And_Answers/JPA/Transaction/getTransaction.htm – Siddharth Jan 07 '13 at 06:48

2 Answers2

8

Finally got the nested transaction not supported error fixed. Changes made to code are

    if (session.getTransaction() != null
            && session.getTransaction().isActive()) {
        txD = session.getTransaction();
    } else {
        txD = session.beginTransaction();
    }

    //txD = session.beginTransaction();
    // txD.begin() ;
    session.saveOrUpdate(dataStore);
    try {
        txD.commit();
        while (!txD.wasCommitted())
            ;
    }

Credits of above code also to Venkat. I did not find HbTransaction, so just used getTransaction and beginTransaction. It worked.

I also made changes in the hibernate properties due to advice on here. I added these lines to the hibernate.properties. This alone did not solve the issue. But I am leaving it there.

hsqldb.write_delay_millis=0
shutdown=true
Community
  • 1
  • 1
Siddharth
  • 9,349
  • 16
  • 86
  • 148
  • Hi As you said .. In my case I am not opening `Trasaction` at all I am sure I am opening `Transaction` only once But still I get `NestedTrasactionException` .. What could be the reason for that – Rookie007 Jul 02 '14 at 03:26
  • Hibernate is very touchy, dont use java fundamentals when coding it. If it works, let it be. The above code is from production and has been working. Thats all I can say – Siddharth Jul 02 '14 at 04:50
  • Okay Thank you .. I will use your code for my case also. – Rookie007 Jul 02 '14 at 06:21
3

You probably already began a transaction before calling this method.

Either this should be part of the enclosing transaction, and you should thus not start another one; or it shouldn't be part of the enclosing transaction, and you should thus open a new session and a new transaction rather than using the current session.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Edited my question to add more details and clarity to it. Please advice. – Siddharth Jan 07 '13 at 03:43
  • For keeping SO neat I have put my answer, but I am accepting your answer for fairness, since you hinted me towards the right solution. Thanks. – Siddharth Jul 04 '13 at 12:23
  • @JB Nizet Hi As you said .. In my case I am not opening `Trasaction` at all I am sure I am opening `Transaction` only once But still I get `NestedTrasactionException` .. What could be the reason for that – Rookie007 Jul 02 '14 at 03:25