我正在为学校开发一个基于Web的数据库前端。但是我对多对多关系有问题。当我注释掉它时,我的服务器启动没有问题。这是启动的堆栈跟踪。
[java] SCHWERWIEGEND: Exception sending context initialized event to listener instance of class org.docadmin.ContextListener
[java] org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
[java] at org.hibernate.collection.AbstractPersistentCollection.setCurrentSession(AbstractPersistentCollection.java:410)
[java] at org.hibernate.event.def.OnUpdateVisitor.processCollection(OnUpdateVisitor.java:43)
[java] at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:101)
[java] at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:61)
[java] at org.hibernate.event.def.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:55)
[java] at org.hibernate.event.def.AbstractVisitor.process(AbstractVisitor.java:123)
[java] at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:293)
[java] at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:223)
[java] at org.hibernate.event.def.DefaultUpdateEventListener.performSaveOrUpdate(DefaultUpdateEventListener.java:33)
[java] at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
[java] at org.hibernate.impl.SessionImpl.fireUpdate(SessionImpl.java:564)
[java] at org.hibernate.impl.SessionImpl.update(SessionImpl.java:552)
[java] at org.hibernate.impl.SessionImpl.update(SessionImpl.java:544)
[java] at org.docadmin.security.DBAuthentication.login(DBAuthentication.java:87)
[java] at org.docadmin.ContextListener.contextInitialized(ContextListener.java:74)
[java] at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4206)
[java] at org.apache.catalina.core.StandardContext.start(StandardContext.java:4705)
[java] at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:799)
[java] at org.apache.catalina.core.ContainerBase.access$000(ContainerBase.java:124)
[java] at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:146)
[java] at java.security.AccessController.doPrivileged(Native Method)
[java] at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:777)
[java] at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:601)
[java] at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:943)
[java] at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:778)
[java] at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:504)
[java] at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1317)
[java] at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:324)
[java] at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:142)
[java] at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1065)
[java] at org.apache.catalina.core.StandardHost.start(StandardHost.java:840)
[java] at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1057)
[java] at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:463)
[java] at org.apache.catalina.core.StandardService.start(StandardService.java:525)
[java] at org.apache.catalina.core.StandardServer.start(StandardServer.java:754)
[java] at org.apache.catalina.startup.Catalina.start(Catalina.java:595)
[java] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[java] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
[java] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[java] at java.lang.reflect.Method.invoke(Method.java:616)
[java] at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
[java] at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)
[java] 02.06.2012 09:42:54 org.apache.catalina.core.StandardContext listenerStart
[java] SCHWERWIEGEND: Exception sending context initialized event to listener instance of class org.docadmin.ContextListener
[java] org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
[java] at org.hibernate.collection.AbstractPersistentCollection.setCurrentSession(AbstractPersistentCollection.java:410)
[java] at org.hibernate.event.def.OnUpdateVisitor.processCollection(OnUpdateVisitor.java:43)
[java] at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:101)
[java] at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:61)
[java] at org.hibernate.event.def.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:55)
[java] at org.hibernate.event.def.AbstractVisitor.process(AbstractVisitor.java:123)
[java] at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:293)
[java] at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:223)
[java] at org.hibernate.event.def.DefaultUpdateEventListener.performSaveOrUpdate(DefaultUpdateEventListener.java:33)
[java] at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
[java] at org.hibernate.impl.SessionImpl.fireUpdate(SessionImpl.java:564)
[java] at org.hibernate.impl.SessionImpl.update(SessionImpl.java:552)
[java] at org.hibernate.impl.SessionImpl.update(SessionImpl.java:544)
[java] at org.docadmin.security.DBAuthentication.login(DBAuthentication.java:87)
[java] at org.docadmin.ContextListener.contextInitialized(ContextListener.java:74)
[java] at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4206)
[java] at org.apache.catalina.core.StandardContext.start(StandardContext.java:4705)
[java] at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:799)
[java] at org.apache.catalina.core.ContainerBase.access$000(ContainerBase.java:124)
[java] at org.apache.catalina.core.ContainerBase$PrivilegedAddChild.run(ContainerBase.java:146)
[java] at java.security.AccessController.doPrivileged(Native Method)
[java] at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:777)
[java] at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:601)
[java] at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:943)
[java] at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:778)
[java] at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:504)
[java] at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1317)
[java] at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:324)
[java] at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:142)
[java] at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1065)
[java] at org.apache.catalina.core.StandardHost.start(StandardHost.java:840)
[java] at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1057)
[java] at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:463)
[java] at org.apache.catalina.core.StandardService.start(StandardService.java:525)
[java] at org.apache.catalina.core.StandardServer.start(StandardServer.java:754)
[java] at org.apache.catalina.startup.Catalina.start(Catalina.java:595)
[java] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[java] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
[java] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[java] at java.lang.reflect.Method.invoke(Method.java:616)
[java] at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
[java] at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)
这是多对多关系的第一个表
@Entity
@Table(name="VFSUSR")
@NamedQueries({
@NamedQuery(name="org.docadmin.db.persistence.vfsusrById",
query="from VfsUser as vfsusr where vfsusr.id = :id"),
@NamedQuery(name="org.docadmin.db.persistence.vfsusrByLogin",
query="from VfsUser as vfsusr where vfsusr.login = :vfsusrlogin"),
})
public class VfsUser
extends AbstractBasePersistableObject
{
/**
* the tables id, primary key
*/
@Id
@Column(name="VFSUSR_ID")
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
/**
* foreign key many to many relationship
*/
@ManyToMany(mappedBy="user")
private Set<VfsGroup> group;
}
多对多关系的第二类。
@Entity
@Table(name="VFSGRP")
@NamedQueries({
@NamedQuery(name="org.docadmin.db.persistence.vfsgrpById",
query="from VfsGroup as vfsgrp where vfsgrp.id = :id"),
@NamedQuery(name="org.docadmin.db.persistence.vfsgrpByGroupName",
query="from VfsGroup as vfsgrp where vfsgrp.groupName = :vfsgrpgroupname"),
})
public class VfsGroup {
/**
* the tables id, primary key
*/
@Id
@Column(name="VFSGRP_ID")
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
/**
* foreign key many to many relationship
*/
@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name="VFSGRPUSR",
joinColumns={@JoinColumn(name="VFSUSR")},
inverseJoinColumns={@JoinColumn(name="VFSGRP")})
private Set<VfsGroup> user;
}
最后是引发异常的代码。
/* retrieve some beans */
sessionFactory = (SessionFactory) ApplicationContextProvider.getApplicationContext().getBean("sessionFactory");
/* retrieve user */
user = userDAO.getVfsUserByLogin(login);
/* open session and begin transaction */
session = sessionFactory.openSession();
tx = session.beginTransaction();
securityToken = null;
try {
if(user != null && Arrays.equals(user.getPassword(), passwordStoreManager.getPasswordStore().encryptPassword(password))){
securityToken = generateToken();
user.setToken(securityToken);
session.update(user);
}
} catch (InvalidKeyException e) {
e.printStackTrace();
logger.error("couldn't login as user[" + login + "] with password[****]", e);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
logger.error("couldn't login as user[" + login + "] with password[****]", e);
} catch (NoSuchPaddingException e) {
e.printStackTrace();
logger.error("couldn't login as user[" + login + "] with password[****]", e);
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
logger.error("couldn't login as user[" + login + "] with password[****]", e);
} catch (BadPaddingException e) {
e.printStackTrace();
logger.error("couldn't login as user[" + login + "] with password[****]", e);
}finally{
/* commit transaction */
tx.commit();
/* close session */
session.close();
}
return(securityToken);
您可能想访问 docadmin 上 sourceforge.net
@Override
public VfsUser getVfsUserByLogin(final String login) {
if(login == null){
return(null);
}
return((VfsUser) getHibernateTemplate().execute(new HibernateCallback() {
public Object doInHibernate(Session session) {
Query query = getSession().getNamedQuery("org.docadmin.db.persistence.vfsusrByLogin");
query.setString("vfsusrlogin", login);
return (VfsUser) query.uniqueResult();
}
}));
}
我会
说错误相当明显。您正在加载一个对象,在本例中是保持打开状态的会话中的用户。然后调用 update,这会尝试将该对象附加到新会话。
这一行:
user = userDAO.getVfsUserByLogin(login);
必须打开会话才能加载用户。然后显式打开另一个会话并调用更新。如果用户已经附加到会话,您实际上不需要调用更新,因为 Hibernate 已经自动检查它。