Java 非法尝试将集合与两个打开的会话关联
我有一个J2EEWeb应用程序,我正在使用hibernate和struts2框架。 该项目在本地服务器上运行良好,但当我将应用程序上载到web上,并且有更多用户同时访问该应用程序时,会引发以下错误:Java 非法尝试将集合与两个打开的会话关联,java,hibernate,session,Java,Hibernate,Session,我有一个J2EEWeb应用程序,我正在使用hibernate和struts2框架。 该项目在本地服务器上运行良好,但当我将应用程序上载到web上,并且有更多用户同时访问该应用程序时,会引发以下错误: Illegal attempt to associate a collection with two open sessions 突然整个hibernate系统崩溃了,我无法执行任何查询。 以下是stacktrace: 'org.hibernate.HibernateException: Ille
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'?>
com.mysql.jdbc.Driver
jdbc:mysql://localhost/hposg?characterEncoding=UTF-8
根
1.
真的
org.hibernate.dialogue.mysqldialogue
线
org.hibernate.cache.NoCacheProvider
更新
以下是我使用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";
}
试试看{
Player=LoginFactory.doLogin(用户名.toLowerCase(),
密码);
会话lSession=HibernateUtil.getSessionFactory()
.getCurrentSession();
lSession.beginTransaction();
lSession.lock(播放器,LockMode.NONE);
player.getInbox().size();
集合未读dmsgs=lSession
.createQuery(
“来自响应者id为“”的消息”
+player.getId()
+“'和message.isRead=false”).list();
lSession.getTransaction().commit();
UserSession.getInstance().addPlayer(播放器);
映射会话=(映射)ActionContext.getContext().get(“会话”);
session.put(“UID”,username.toLowerCase());
会话。put(“类型”、“玩家”);
一场
.put(“名称”,player.getName()+“”
+player.getFamily());
session.put(“UNREADMSGS”,UNREADMSGS.size());
session.put(“上次查看的游戏ID”,0);
回归成功;
}捕获(LoginException a){
addActionError(a.getMessage());
返回“错误”;
}捕获(例外a){
addActionError(如getMessage());
返回“错误”;
}
我错过了什么吗?
有什么想法吗?您的代码显示您创建了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;
}
请确认您正在使用XWork操作类作为Springbean? 如果是这样的话,可能您忘记了遵循Struts2/Spring中的指令,即当您将actionbean作为springbean(在依赖注入控制器中)时。。。 您需要将bean声明为非单例! 在声明中,确保您具有singleton=“false”属性
如果你忘了做这个会怎么样?一个用户访问相同的操作,一切正常。超过1个用户访问您的bean,您在单例bean中有竞争条件。我怀疑你的应用程序中确实发生了这种情况。显然,使用merge可能会解决这个问题
myInstance = (myInstanceClass) Session.merge(myInstance);
这有什么用?UserSession.getInstance();UserSession.addPlayer(播放器);显示您的
LoginAction
和hibernate.cfg.xml
。UserSession只是一个包含已登录用户哈希映射的类。addPlayer()中的代码是线程安全的吗?事实上,这个类与hibernate无关,我不保存这个对象。它只是一个容器,用来存放在线用户。但你的观点似乎是一个有希望的线索!我根本没有考虑整个项目中的线程安全问题。你还有什么特别的建议吗?天哪!似乎很有道理。你说得对,伙计。(我们应该和这部分的程序员做些生意!:D)。但出于好奇,为什么每个doLogin都不会发生这种情况,错误也会不规则地发生?不幸的是,问题仍然存在:(我检查了代码的每个部分,并将所有会话都更改了。beginTransaction().commit();改为session.getTransaction().commit()),但这种情况再次发生。谢谢Daniel,实际上我根本没有使用spring,但我确实使用struts操作作为控制器。我也没有任何单例对象,但有一个类(名为HPOSG)其中我有很多静态方法,很可能同时被访问。这些方法不操纵任何数据,它们只是作为hibernate和业务类之间的桥梁。在整个应用程序中,每当我需要集合或其他东西时,我都会要求这些方法为我提供它们。
myInstance = (myInstanceClass) Session.merge(myInstance);