休眠:同时有两个或多个事务:事务已经处于活动状态

Car*_*arí 4 java rest hibernate jersey

我有一个 REST API,当我几乎同时进行 POST 和 GET 时,我收到此异常:

 SEVERE: The RuntimeException could not be mapped to a response, re-throwing to the HTTP container
java.lang.IllegalStateException: Transaction already active
    at org.hibernate.engine.transaction.internal.TransactionImpl.begin(TransactionImpl.java:52)
    at org.hibernate.internal.AbstractSharedSessionContract.beginTransaction(AbstractSharedSessionContract.java:409)
    at sun.reflect.GeneratedMethodAccessor89.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:355)
    at com.sun.proxy.$Proxy58.beginTransaction(Unknown Source)
    at utils.HibernateSession.createTransaction(HibernateSession.java:15)
    at api.ConversationsREST.getMessages(ConversationsREST.java:128)
Run Code Online (Sandbox Code Playgroud)

它们位于不同的类上,因此没有隐含的全局属性。

失败的那一行是:

HibernateSession hs = new HibernateSession();
hs.createTransaction(); // Crash
Run Code Online (Sandbox Code Playgroud)

Wich 指的是我的类 HibernateSession:

public class HibernateSession {

    public Session session;

    public void createTransaction() {

        session = HibernateUtil.getSessionFactory().getCurrentSession(); //THIS WAS WRONG
 //EDIT:session = HibernateUtil.getSessionFactory().openSession(); //THIS IS RIGHT
        session.beginTransaction();
    }

    public void commitclose() {

        session.getTransaction().commit();
        session.close();

    }

    public void rollbackclose() {

        try {
            session.getTransaction().rollback();
            session.close();
        } catch (Exception hibernateexception) {
            hibernateexception.printStackTrace();
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

异常其实就上线了 session.beginTransaction()

我总是做一个 hs.commitclose() 并且在 catch() 块和 404s 我总是做一个 rollbackclose();

问题是,当我发出这样的 POST 消息时:

HibernateSession hs = new HibernateSession();
hs.createTransaction();
hs.session.save(whatever);
hs.commitclose();
Run Code Online (Sandbox Code Playgroud)

返回 200 就可以了,但是 GET 可能会因上述异常而崩溃。在我创建HibernateSession的实例时,为什么 Hibernate 似乎试图共享该事务?

这只发生在我在很短的时间内进行两个查询时(我想在另一个人的开始和提交之间开始一个事务)。所以我猜 Hibernate 认为会话属性是静态的或类似的东西......

预先感谢您的帮助!

编辑:根据要求,HibernateUtil.java(问题一定不在这里,但可能有助于理解):

package utils;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

    private static SessionFactory sessionFactory;

    public static SessionFactory getSessionFactory() {

        if (sessionFactory == null) {

            sessionFactory = build();

        }
        return sessionFactory;

    }

    private static SessionFactory build() {

        try {

            return new Configuration().configure().buildSessionFactory();

        } catch (Throwable ex) {

            System.err.println("Initial SessionFactory creation failed: " + ex);
            throw new ExceptionInInitializerError(ex);
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

MyT*_*nts 7

根据您的createTransaction逻辑,您正在从中获取当前会话SessionFactory并从中启动事务。

这是问题所在。

假设您已经创建了HibernateSession对象并启动了事务,但它仍在进行中。所以你还没有关闭交易。

现在您创建了另一个HibernateSession并尝试启动事务,这样做会引发异常。

所以你的这个代码

public void createTransaction() {
    session = HibernateUtil.getSessionFactory().getCurrentSession();
    session.beginTransaction();
}
Run Code Online (Sandbox Code Playgroud)

必须是这个

public void createTransaction() {
    session = HibernateUtil.getSessionFactory().openSession();
    session.beginTransaction();
}
Run Code Online (Sandbox Code Playgroud)

getSessionFactory().openSession()总是会打开一个新会话,一旦您完成操作,您必须关闭该会话。

getSessionFactory().getCurrentSession()返回绑定到上下文的会话 - 您不需要关闭它。