我正在使用带有mysql和hibernate 4和c3p0的球衣。我创建了一个初始化servlet来配置hibernate并将当前会话上下文类设置为thread。 我创建了hibernateUtils类,它包含用于获取和提交会话的静态方法,我使用过滤器来启动入站请求的会话并在响应时提交它。
问题是,在某些随机的时间间隔我得到org.hibernate.TransactionException:嵌套事务不支持异常,但我不是在尝试创建一个新的会话,除了在过滤器上。
如果我错了,请纠正我,但在将当前会话类设置为线程时,我不需要在hibernateutil中创建threadlocal,hibernate会这样做。所以我的问题是,这是一种安全的方法来处理这种情况以及可能导致错误随机发生的原因吗?
======================编辑======================== ===
很抱歉没有提前发布代码。 所以过滤器实现了ContainerRequestFilter,ContainerResponseFilter
我正在执行的请求过滤器中的
Session session = sessionfactory.getCurrentSession();
session.getTransaction().begin();
session.setDefaultReadOnly(readOnly);
并在回复中
Transaction transaction = sessionfactory.getCurrentSession().getTransaction();
try {
if (transaction != null && !transaction.wasCommitted()
&& !transaction.wasRolledBack() && transaction.isActive()) {
transaction.commit();
}
} catch (HibernateException e) {
Transaction transaction = sessionfactory.getCurrentSession().getTransaction();
try {
if (transaction != null && transaction.isActive()) {
transaction.rollback();
}
} catch (HibernateException e) {
} finally {
Session session = sessionfactory.getCurrentSession();
try {
if (session != null && session.isOpen()) {
session.close();
}
} catch (HibernateException e) {
log.error("Closing session after rollback error: ", e);
throw e;
}
}
答案 0 :(得分:1)
您似乎在过滤器中使用程序化事务划分(据我所知)。因此,请仔细检查您是否正确终止了每个事务,不要在请求期间附加什么附加信息(例如,如果您获得异常则回滚并以其他方式提交):
try {
session.getTransaction().begin();
// call the filter chain
session.getTransaction().commit()
}
catch (RuntimeException e) {
session.getTransaction().rollback();
}
没有代码,很难确定,但我想对于某些请求,您没有正确终止事务(即通过提交或回滚)。所以事务仍然与线程相关联,并且线程返回到线程池(在一个非常奇怪的状态,因为仍然存在与之关联的事务),然后另一个请求重用相同的线程,在过滤器中创建一个新的事务......你得到了例外。
修改强>
在仔细查看您的代码后,它(可能)确认了我的假设。
查看transaction.wasRolledBack()==true
时的流程:它不会被提交也不会回滚。
如果你是Transaction.wasRolledBack()的javadoc:
此事务是否已回滚或设置为仅回滚?
如果事务被标记为“仅RollBack”:它将返回true,但这并不意味着事务已结束。这意味着该事务唯一可能的结束状态是“RollBack”。
但是,另一方面,同样的javadoc也这样说:
返回:boolean如果事务是通过此本地事务回滚的,则为True;否则就是假的。
我发现这个含糊不清。
所以我建议你这样做:
if (transaction != null && !transaction.wasCommitted()
&& !transaction.wasRolledBack() && transaction.isActive()) {
transaction.commit();
}else if(transaction.wasRolledBack()){
transaction.rollback();
}