我有一个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)
它们位于不同的类上,因此没有暗示全局属性。
失败的行是这一行:
HibernateSession hs = new HibernateSession();
hs.createTransaction(); // Crash
Wich指的是我的 class 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();
}
}
}
异常实际上在
session.beginTransaction()
行上我总是做一个hs.commitclose(),在catch()块和404中我总是做一个rollbackclose();
问题是当我发出这样的POST消息时:
HibernateSession hs = new HibernateSession();
hs.createTransaction();
hs.session.save(whatever);
hs.commitclose();
返回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);
}
}
}
最佳答案
根据createTransaction
逻辑,您正在从SessionFactory
获取当前会话并从中开始事务。
这是问题所在。
假设您已经创建了HibernateSession
对象并开始了事务,但是该事务仍在进行中。因此,您尚未关闭交易。
现在,您创建了另一个HibernateSession
并尝试启动事务,这样做将引发异常。
所以你的这段代码
public void createTransaction() {
session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
}
必须是这个
public void createTransaction() {
session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
}
getSessionFactory()。openSession()总是打开一个新会话,您必须在完成操作后关闭该会话。
getSessionFactory()。getCurrentSession()返回绑定到上下文的会话-您无需关闭它。