Hibernate 4.1.9(最新的最终版本)报告`不支持嵌套事务`

时间:2013-01-06 17:23:37

标签: java multithreading hibernate asynchronous

我正在

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)

抛出该异常的代码。我从一个运行无限的线程调用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();
}

编辑: 我在一个独立的线程中调用flush,因为数据存储列表包含数据。从我看到它的同步操作调用到flush,所以理想情况下flush应该不会返回,直到事务完成。我希望这种方式是我想要的最少。由于它是一个完成其工作的独立线程,所以我关心它是同步操作。现在我的问题是,txD.com发出异步操作吗?在交易有机会完成之前是否返回。如果是,是否有办法提交“等待”直到事务完成?

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

编辑2:添加了while(!txD.wasCommitted()) ;(在上面的代码中),我仍然感到害怕nested transactions not supported。事实上,由于这个例外,表也没有写入记录。是否与表格类型有关?我的所有桌子都有INNODB吗?

2 个答案:

答案 0 :(得分:8)

最后修复了nested transaction not supported错误。对代码所做的更改

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

以上代码的信用也归Venkat所示。我没有找到HbTransaction,所以只使用了getTransaction和beginTransaction。它奏效了。

由于对here的建议,我还对hibernate属性进行了更改。我将这些行添加到hibernate.properties中。仅这一点并没有解决问题。但是我把它留在那里。

hsqldb.write_delay_millis=0
shutdown=true

答案 1 :(得分:3)

在调用此方法之前,您可能已经开始了一个事务。

这应该是封闭交易的一部分,因此你不应该开始另一个;或者它不应该是封闭交易的一部分,因此您应该打开一个新的会话和一个新的交易,而不是使用当前的会话。