在webservice + hibernate中发生死锁......不知道为什么。休眠死锁
我有以下的Web服务代码(函数的核心代码)
public String createImageRecipe(...)
{
Session session = ICDBHibernateUtil.getSessionFactory().getCurrentSession();
try
{
session.beginTransaction();
User user = (User) session.load(User.class, userid);
// Create the recipe
Recipe recipe = new Recipe();
...
...
...
session.save(recipe);
session.save(user);
...
...
...
session.update(recipe);
// Add new entry to activity log
Activitylog activityLog = new Activitylog( user,
(byte) ActivityTypeEnum.USER_SHARED_RECIPE.ordinal(),
new Date());
activityLog.setRecipe(recipe);
TimelineProcessor.saveTimeline(activityLog, null, true);
session.getTransaction().commit();
endMeasurement();
return recipe.getRecipeid() + "," + recipe.getImageRecipeUrl();
}
catch (RuntimeException e)
{
ICDBHibernateUtil.getSessionFactory().getCurrentSession().getTransaction().rollback();
throw e;
}
}
现在的时间表线程(TimelineProcessor)进行以下(得到消息后):
Session session = ICDBHibernateUtil.getTimelineSessionFactory().openSession();
try {
session.getTransaction().begin();
...
...
...
TimelineId tlId = new TimelineId();
tlId.setUserId(userId);
User u = new User();
u.setUserid(userId);
Timeline tl = new Timeline(tlId, timelineData.getActivitylog(), u);
session.save(tl);
session.getTransaction().commit();
session.close();
} catch (Exception e) {
logger.error("Error while processing timeline :: ", e);
session.getTransaction().rollback();
}
}
从异常日志: 引起:com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:尝试获取锁定时发现的死锁;尝试sun.reflect.NativeConstructorAccessorImpl.newInstance0(本机方法)
org.hibernate.HibernateException重启交易 :非法尝试用两次公开会议 集合在org.hibernate.collection.AbstractPersistentCollection.setCurrentSession(AbstractPersistentCollection关联。的java:435)
ERROR com.icdb.TimelineProcessor - processTimeline - 错误而处理的时间表:: org.hibernate.exception.LockAcquisitionException:无法插入:[com.icdb.data.Activitylog]
引起通过:com.mysql.jdbc.exceptions.jd bc4.MySQLTransactionRollbackException:尝试获取锁定时发现的死锁;尝试sun.reflect.NativeConstructorAccessorImpl.newInstance0(本机方法)
ERROR com.icdb.TimelineProcessor重启交易 - processTimeline - 错误在处理时间表:: org.hibernate.HibernateException:非法尝试集合有两个关联打开的会话
真的会帮助并欣赏... 非常感谢
我明白了。那么时间线是用来记录所有的用户活动(以时间线的形式显示,就像在facebook中一样)。我在一个线程中使用它,因为我需要服务调用的速度很快,而且这可以在BG中完成。所以我从你的回答中了解到 - 我应该通过Ids和创建用户u =新用户(); u.setId(i_userId),所以如果理解正确,那么它应该解决这个问题? – user1136875
这就是我会这样做的,特别是因为你有一个SessionFactory和一个TimelineSessionFactory,这是一个提示,有一天时间轴可能最终存储在一个完全不同的数据库服务器上,然后你需要传递消息而不是实体。如何实现它是另一个问题:您可以让TimelineService只接收原始数据,如int和Strings,然后应用程序的其他部分也可以访问它,而无需知道User类。或者您可以使用DTO副本,或者自己制作,或者使用推土机等工具。两种方式都有优点。 – wallenborn
非常感谢。是一个很大的帮助。明白了你的观点 – user1136875