0

在 webservice + hibernate 中陷入僵局......不知道为什么。

我有以下webservice代码(函数的核心代码)

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(Native Method) 处重新启动事务

org.hibernate.HibernateException:非法尝试将集合与 org.hibernate.collection.AbstractPersistentCollection.setCurrentSession(AbstractPersistentCollection.java:435) 处的两个打开会话相关联

ERROR com.icdb.TimelineProcessor - processTimeline - Error while processing timeline :: org.hibernate.exception.LockAcquisitionException: could not insert: [com.icdb.data.Activitylog]

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

ERROR com.icdb.TimelineProcessor - processTimeline - Error while processing timeline :: org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions

Will really appriciate help... Thanks a lot

4

1 回答 1

2

Well Hibernate is telling you what it doesn't like:

Illegal attempt to associate a collection with two open sessions

You are opening two sessions, and have a transaction in each, and when you save the new timeline in the second session, it has an activityLog, and that activityLog has a user and a recipe that stem from the first session. That's where Hibernate croaks.

I'm not sure i see what you are trying to accomplish. Is there a reason you need two separate sessions? Is the timeline something that's semantically associated with the recipe/user entities or is it more like a timestamp collection? In the former case you probably want to store user, recipe and timeline in one and the same collection, or else you'll end up with corrupt data if one transaction succeeds and the other one fails. In the latter case the Timestamp service should take value objects as arguments rather than entities, because you're probably going to want to access it from different parts of your application.

于 2012-06-21T16:21:20.773 回答