Java 休眠:同时有两个或多个事务:事务已处于活动状态
我有一个REST API,当我几乎同时发布POST和GET时,我会遇到以下异常:Java 休眠:同时有两个或多个事务:事务已处于活动状态,java,hibernate,rest,jersey,Java,Hibernate,Rest,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.T
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指的是我的班级休眠会话:
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()块和404s中我总是做一个rollbackclose()
问题是,当我发布这样的消息时:
HibernateSession hs = new HibernateSession();
hs.createTransaction();
hs.session.save(whatever);
hs.commitclose();
返回200,这是正常的,但是GET可能会崩溃,出现上述异常。
当我创建一个新的HibernateSession实例时,为什么Hibernate似乎试图共享该事务
只有当我在很短的时间内进行两次查询时(我猜是在另一个查询的开始和提交之间启动事务),才会发生这种情况。所以我猜Hibernate认为会话属性是静态的或者类似的东西
提前感谢您的帮助!
编辑:根据请求,HibernateUtil.java
(问题一定不在这里,但可能有助于理解):
尝试将代码重新编写为
public class HibernateSession {
public Session session;
int id;
Transaction t = null;
public void createTransaction() {
session = HibernateUtil.getSessionFactory().getCurrentSession();
t = session.beginTransaction();
}
public void commitclose() {
t.commit();
session.close();
}
public void rollbackclose() {
try {
t.rollback();
session.close();
} catch (Exception hibernateexception) {
hibernateexception.printStackTrace();
}
}
}
对于
t
的每个引用,都需要进行非正常的空检查。根据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()返回绑定到上下文的会话-您不需要关闭它。实际上,您的实际代码中有许多缺点:
- 每次调用代码时,您都在创建
类的一个新实例,因此您将有许多实例试图访问同一会话HibernateSession
- 调用
hs.createTransaction()时,
的每个实例都将尝试创建一个新事务代码>,这就是为什么在这一行出现异常,因为已经有打开的事务,并且您正在尝试打开一个新的事务,因为您正在调用HibernateSession
session.beginTransaction()每次不调用
transaction.close()代码>
HibernateSession
类成为单例,因此只有一个实例可用,您可以查看该实例以了解如何实现它的更多详细信息
在
createTransaction
方法中,wich应该更好地命名为getTransaction
,而不是只调用session.beginTransaction()
如果当前事务存在,您需要获取它。您可以使用session.getTransaction()
方法检查它,并确保将代码包装在try…catch
块中,您可以检查它以了解更多详细信息。您有一些与设计相关的缺陷:
getCurrentSession()
Session sess = factory.openSession();
Transaction tx;
try {
tx = sess.beginTransaction();
//do some work
...
tx.commit();
}
catch (Exception e) {
if (tx!=null) tx.rollback();
throw e;
}
finally {
sess.close();
}
finally{session.close()}
——以确保在退出该方法时会话已关闭。我假设在某个时刻,您的commit()
没有成功,并在此后未关闭的事务/会话中离开了休眠状态
要解决这个问题,您应该在代码中插入一个session.close(),执行它,然后实现我建议的try-catch-finally块,以确保它在将来关闭。我刚刚更改了它
session = HibernateUtil.getSessionFactory().getCurrentSession();
与
我正在访问已打开的工厂会话。是否可以添加HibernateUtil…@Ashish451当然我已经添加了解决方案。。您可以尝试执行相同的异常,但不执行session.beginTransaction();它在t=session.beginTransaction()上;最后一次尝试。替换
t=session.beginTransaction()代码>带有t=session.getTransaction()代码>但我需要开始。它应该是非活动的,因为我第一次获取。我可以检查是否处于活动状态,但这只是一个解决方法,我真正需要的是每次类实例化时,事务都成为一个非常新的实例。@CarlosLópez这就是为什么您应该使用会话工厂!您只有一个Hibernate会话的实例,而其中一个被卡在事务中,因为您没有正确关闭它。@nwenz3l是的,问题出在getCurrentTransaction()上,而不是我想做的openTransaction上。正如您在编辑中看到的,他有一个单例工厂,可以用来实例化新会话,那太好了。他的实际错误是,在提交给b的方法中没有finally{session.close()}
或者甚至没有try{..}
session = HibernateUtil.getSessionFactory().getCurrentSession();
session = HibernateUtil.getSessionFactory().openSession();