问题描述
我有一个REST API,当我几乎同时进行POST和GET时,出现此异常:
I have a REST API and when i make a POST and a GET nearly the same time i get this exception:
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)
它们在不同的类上,因此没有暗示全局属性.
They are on different classes so no global attributes implied.
失败的那一行是这个:
HibernateSession hs = new HibernateSession();
hs.createTransaction(); // Crash
这是指我的课程HibernateSession:
Wich refers to my 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();
I always make a hs.commitclose() and in the catch() blocks and the 404s I always make a rollbackclose();
问题是当我发出这样的POST消息时:
The problem is that when I make a POST messages like this:
HibernateSession hs = new HibernateSession();
hs.createTransaction();
hs.session.save(whatever);
hs.commitclose();
返回200,就可以了,但是GET可能会崩溃,但上面的异常除外.在创建HibernateSession的 new 实例时,为什么Hibernate似乎试图共享该交易?
Returns 200 and it's ok but then the GET may crash with the exception above.As I am makeing a new instance of HibernateSession, why Hibernate seems to be trying to share that transaction?
仅当我在很短的时间内进行两个查询时才会发生这种情况(我猜想在另一个人的开始和提交之间开始一个事务).所以我猜Hibernate认为会话属性是静态的或类似的东西...
This only happens when I make both querys in a very short time (i guess starting a transaction between the beginning and the commit of anotherone). So i guess Hibernate is thinking that session attribute is static or something like that...
:根据要求,HibernateUtil.java
(问题一定不在这里,但可能有助于理解):
As requested, HibernateUtil.java
(the problem must not be here but may help to understand):
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
获取当前会话并从中开始事务.
As per your createTransaction
logic, you are getting current session from SessionFactory
and starting a transaction from it.
这是问题所在.
让我们假设您已经创建了HibernateSession
对象并开始了事务,但是该事务仍在进行中.因此,您尚未关闭交易.
Lets assume you have created HibernateSession
object and started transaction but it is still in progress. So you haven't close transaction yet.
现在您创建了另一个HibernateSession
并尝试启动事务,这样做将引发异常.
Now you created another HibernateSession
and try to start transaction, doing this will throw exception.
所以您的这段代码
public void createTransaction() {
session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
}
必须是
public void createTransaction() {
session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
}
getSessionFactory().openSession()始终会打开一个新会话,您必须在完成操作后关闭该会话.
getSessionFactory().openSession() always opens a new session that you have to close once you are done with the operations.
getSessionFactory().getCurrentSession()返回绑定到上下文的会话-您无需关闭该会话.
getSessionFactory().getCurrentSession() returns a session bound to a context - you don't need to close this.
这篇关于休眠:同时进行两个或多个事务:事务已激活的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!