Hibernate死锁

时间:2012-06-21 15:30:07

标签: hibernate deadlock

在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:非法尝试将集合与两个打开的会话相关联

真的会帮助... 非常感谢

1 个答案:

答案 0 :(得分:2)

Hibernate告诉你它不喜欢什么:

Illegal attempt to associate a collection with two open sessions

您正在打开两个会话,并在每个会话中都有一个事务,当您在第二个会话中保存新时间轴时,它有一个activityLog,并且该activityLog有一个用户和来自第一个会话的配方。这就是Hibernate呱呱叫的地方。

我不确定我看到你想要完成什么。你需要两个单独的会话吗?时间线是否与配方/用户实体在语义上相关联,或者它更像是时间戳集合?在前一种情况下,您可能希望将用户,配方和时间线存储在同一个集合中,否则如果一个事务成功而另一个事务失败,您将最终得到损坏的数据。在后一种情况下,Timestamp服务应该将值对象作为参数而不是实体,因为您可能希望从应用程序的不同部分访问它。