非法尝试将集合与两个打开的会话相关联

时间:2011-01-22 21:30:38

标签: java hibernate session

我有一个j2ee Web应用程序,我正在使用hibernate和struts2框架。 该项目在本地服务器上运行正常,但是当我在Web上传应用程序并且更多用户同时访问它时,会抛出此错误:

Illegal attempt to associate a collection with two open sessions

突然整个hibernate系统崩溃,我无法执行任何查询。 这是stacktrace:

'org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
    at org.hibernate.collection.AbstractPersistentCollection.setCurrentSession(AbstractPersistentCollection.java:432)
    at org.hibernate.event.def.WrapVisitor.processCollection(WrapVisitor.java:67)
    at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:124)
    at org.hibernate.event.def.WrapVisitor.processValue(WrapVisitor.java:121)
    at org.hibernate.event.def.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:78)
    at org.hibernate.event.def.DefaultFlushEntityEventListener.wrapCollections(DefaultFlushEntityEventListener.java:218)
    at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:152)
    at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:219)
    at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
    at org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:58)
    at org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:1175)
    at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1251)
    at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
    at org.hibernate.impl.AbstractQueryImpl.uniqueResult(AbstractQueryImpl.java:859)
    at com.hposg.login.LoginFactory.doLogin(LoginFactory.java:31)
    at com.hposg.controller.struts.LoginAction.execute(LoginAction.java:50)
    at sun.reflect.GeneratedMethodAccessor489.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:616)
    at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:441)
    at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:280)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:243)
    at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:165)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:252)
    at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:68)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:122)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:195)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:195)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:179)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:75)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:94)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:235)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:89)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:130)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:267)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:126)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:138)
    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:87)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:165)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:179)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:176)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:237)
    at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:52)
    at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:488)
    at org.apache.struts2.dispatcher.FilterDispatcher.doFilter(FilterDispatcher.java:395)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:636)

这是引起这个问题的代码:

public static Player doLogin(String ID, String pass) throws LoginException , BanedUser{

        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();

        Player player = (Player) session.createQuery(
                "from Player as player where player.loginName = " + "'" + ID
                        + "' and player.passWord ='" + pass + "'")
                .uniqueResult();

        if (player == null)
            throw new LoginException();
        else if (!player.getIsActive())
            throw new BanedUser();

        UserSession.getInstance();
        UserSession.addPlayer(player);

        session.beginTransaction().commit();

        return player;
    }

错误不定期发生(每周一次,每隔一天等),任何可能导致此问题的想法?


这是我的hibernate.cfg.xml:

<?xml version='1.0' encoding='utf-8'?>

    

    <!-- Database connection settings -->
    <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">
        jdbc:mysql://localhost/hposg?characterEncoding=UTF-8
    </property>
    <property name="connection.username">root</property>
    <property name="connection.password"></property>

    <!-- JDBC connection pool (use the built-in) -->
    <property name="connection.pool_size">1</property>

    <!-- Echo all executed SQL to stdout -->
    <property name="show_sql">true</property>

    <!-- SQL dialect -->
    <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

    <!-- Enable Hibernate's automatic session context management -->
    <property name="current_session_context_class">thread</property>

    <!-- Disable the second-level cache -->
    <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

    <!-- Drop and re-create the database schema on startup -->
    <property name="hbm2ddl.auto">update</property>

  <!-- Mapping files -->

  <mapping resource="com/hposg/hibernate/resources/Player.hbm.xml"/>
  <mapping resource="com/hposg/hibernate/resources/Game.hbm.xml"/>
  <mapping resource="com/hposg/hibernate/resources/Portfolio.hbm.xml"/>
  <mapping resource="com/hposg/hibernate/resources/Purchase.hbm.xml"/>
  <mapping resource="com/hposg/hibernate/resources/Sale.hbm.xml"/>
  <mapping resource="com/hposg/hibernate/resources/Message.hbm.xml"/>
  <mapping resource="com/hposg/hibernate/resources/Admin.hbm.xml"/>
  <mapping resource="com/hposg/hibernate/resources/News.hbm.xml"/>
  <mapping resource="com/hposg/hibernate/resources/Invitation.hbm.xml"/>
  <mapping resource="com/hposg/hibernate/resources/CustomGameCreationRequest.hbm.xml"/>
  <mapping resource="com/hposg/hibernate/resources/Alert.hbm.xml"/>
  <mapping resource="com/hposg/hibernate/resources/AlertLimits.hbm.xml"/>
  <mapping resource="com/hposg/hibernate/resources/StockIndex.hbm.xml"/>      
  <mapping resource="com/hposg/hibernate/resources/HPOSG.hbm.xml"/>  
  <mapping resource="com/hposg/hibernate/resources/Tradeable.hbm.xml"/>
  <mapping resource="com/hposg/hibernate/resources/GlobalGameConfig.hbm.xml"/>
  <mapping resource="com/hposg/hibernate/resources/Announcement.hbm.xml"/>  
  <mapping resource="com/hposg/hibernate/resources/AdviserMsg.hbm.xml"/>
  <mapping resource="com/hposg/hibernate/resources/SystemConfiguration.hbm.xml"/>  
</session-factory>

以下是我的LoginAction作为我使用hibernate的策略的一个例子:

try {
            Player player = LoginFactory.doLogin(username.toLowerCase(),
                    password);

            Session lSession = HibernateUtil.getSessionFactory()
                    .getCurrentSession();
            lSession.beginTransaction();

            lSession.lock(player, LockMode.NONE);
            player.getInbox().size();
            Collection<Message> unreadMsgs = lSession
                    .createQuery(
                            "FROM Message message WHERE Respondent.id='"
                                    + player.getId()
                                    + "' AND message.isRead=false").list();

            lSession.getTransaction().commit();

            UserSession.getInstance().addPlayer(player);
            Map session = (Map) ActionContext.getContext().get("session");
            session.put("UID", username.toLowerCase());
            session.put("TYPE", "PLAYER");
            session
                    .put("NAME", player.getName() + " "
                            + player.getFamily());
            session.put("UNREADMSGS", unreadMsgs.size());
            session.put("LAST_VIEWED_GAME_ID", 0);
            return SUCCESS;
        } catch (LoginException a) {
            addActionError(a.getMessage());
            return "error";
        } catch (Exception a) {
            addActionError(e.getMessage());
            return "error";
        }
我失踪了吗? 任何想法?

3 个答案:

答案 0 :(得分:2)

您的代码显示您创建了2个交易....试试这个: -

public static Player doLogin(String ID, String pass) throws LoginException , BanedUser{

        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        Transaction tx = session.beginTransaction();

        ...

        tx.commit();

        return player;
    }

答案 1 :(得分:0)

请确认您使用XWork操作类作为Spring bean? 如果是这种情况,可能你忘了遵循Struts2 / Spring中的指令,当你有动作bean作为Spring bean时(在Dependency Injection控制器中)... 你需要将bean声明为非单例! 在声明中确保您有 singleton =“false”属性。

如果你忘记这样做会怎么样?一个用户访问相同的操作,一切正常。超过1个用户访问您的bean,您在单例bean中有竞争条件。我怀疑你的应用程序确实发生了什么。

答案 2 :(得分:0)

显然使用合并可能会解决问题

myInstance = (myInstanceClass) Session.merge(myInstance);