在webservice + hibernate中出现死锁......不知道为什么。
我有以下网络服务代码(该功能的核心代码)
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:尝试获取锁定时发现死锁;尝试重新启动事务 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
org.hibernate.HibernateException:非法尝试将集合与两个打开的会话相关联 在org.hibernate.collection.AbstractPersistentCollection.setCurrentSession(AbstractPersistentCollection.java:435)
错误com.icdb.TimelineProcessor - processTimeline - 处理时间轴时出错:: org.hibernate.exception.LockAcquisitionException:无法插入:[com.icdb.data.Activitylog]
引起:com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:尝试获取锁定时发现死锁;尝试重新启动事务 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
错误com.icdb.TimelineProcessor - processTimeline - 处理时间轴时出错:: org.hibernate.HibernateException:非法尝试将集合与两个打开的会话相关联
真的会帮助... 非常感谢
答案 0 :(得分:2)
Hibernate告诉你它不喜欢什么:
Illegal attempt to associate a collection with two open sessions
您正在打开两个会话,并在每个会话中都有一个事务,当您在第二个会话中保存新时间轴时,它有一个activityLog,并且该activityLog有一个用户和来自第一个会话的配方。这就是Hibernate呱呱叫的地方。
我不确定我看到你想要完成什么。你需要两个单独的会话吗?时间线是否与配方/用户实体在语义上相关联,或者它更像是时间戳集合?在前一种情况下,您可能希望将用户,配方和时间线存储在同一个集合中,否则如果一个事务成功而另一个事务失败,您将最终得到损坏的数据。在后一种情况下,Timestamp服务应该将值对象作为参数而不是实体,因为您可能希望从应用程序的不同部分访问它。