今天碰到了一个 奇怪的问题 Illegal attempt to associate a collection with two open sessions。 在最后提交逻辑里。 以前也说过, 现在这个项目的事务是利用AOP 加到DAO 层上的, 在EJB 的方法中很容易在一个方法里面多次调用DAO 层。 并且由于是在做mass change 之前要取出原业务对象 然后在merge 上mass change 的数据。 然后在做N 多的校验, 到最后校验通过提交数据。
这个异常的 log 如下:
org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
at org.hibernate.exception.NestableRuntimeException.<init>(NestableRuntimeException.java:104) ~[hibernate-3.2.6.ga.jar:3.2.6.ga]
at org.hibernate.collection.AbstractPersistentCollection.setCurrentSession(AbstractPersistentCollection.java:403) ~[hibernate-3.2.6.ga.jar:3.2.6.ga]
at org.hibernate.event.def.OnUpdateVisitor.processCollection(OnUpdateVisitor.java:43) ~[hibernate-3.2.6.ga.jar:3.2.6.ga]
at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:101) ~[hibernate-3.2.6.ga.jar:3.2.6.ga]
at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:61) ~[hibernate-3.2.6.ga.jar:3.2.6.ga]
at org.hibernate.event.def.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:55) ~[hibernate-3.2.6.ga.jar:3.2.6.ga]
at org.hibernate.event.def.AbstractVisitor.process(AbstractVisitor.java:123) ~[hibernate-3.2.6.ga.jar:3.2.6.ga]
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:293) ~[hibernate-3.2.6.ga.jar:3.2.6.ga]
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:223) ~[hibernate-3.2.6.ga.jar:3.2.6.ga]
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:89) ~[hibernate-3.2.6.ga.jar:3.2.6.ga]
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70) ~[hibernate-3.2.6.ga.jar:3.2.6.ga]
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507) ~[hibernate-3.2.6.ga.jar:3.2.6.ga]
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499) ~[hibernate-3.2.6.ga.jar:3.2.6.ga]
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:495) ~[hibernate-3.2.6.ga.jar:3.2.6.ga]
进入 OnUpdateVisitor.java的第 43 行代码 可以看到
PersistentCollection wrapper = (PersistentCollection) collection;
if ( wrapper.setCurrentSession(session) ) {
的确在我们的DAO 中要保存的对象有一个 List 成员 所以 这个 wrapper 就是Hibernate 在 load 出那个 entity 的时候产生出的对应的PersistentCollection 集合了, 它应该还保留当时的那个DAO 用到的。 我们再到AbstractPersistentCollection.setCurrentSession 方法里看看:
public final boolean setCurrentSession(SessionImplementor session) throws HibernateException {
if (session==this.session) {
return false;
}
else {
if ( isConnectedToSession() ) {
CollectionEntry ce = session.getPersistenceContext().getCollectionEntry(this);
if (ce==null) {
throw new HibernateException(
"Illegal attempt to associate a collection with two open sessions"
);
}
else {
throw new HibernateException(
"Illegal attempt to associate a collection with two open sessions: " +
MessageHelper.collectionInfoString(
ce.getLoadedPersister(),
ce.getLoadedKey(),
session.getFactory()
)
);
}
}
else {
this.session = session;
return true;
}
}
}
在这个方法里面程序的行为应该是:
1, isConnectedToSession() 应该返回为true, 当然这个Session 不是当前这个Session,而是开始load 的那个DAO 对应的Session,
2,接下来一行 CollectionEntry ce = session.getPersistenceContext().getCollectionEntry(this);就返回 null 了,
3 ,if (ce==null) {
throw new HibernateException(
"Illegal attempt to associate a collection with two open sessions"
);
}
解决的方法 有两个:
1, 首先 Object mergedEntity = Session.merge(entity), 然后 saveOrUpdate 这个 mergedEntity。
2, Session.lock (entity, Lock.NONE)。
其实这个 lock 的用法还是从 这个地方google来的, 在此留个记号,需要做进一步的学习。
分享到:
相关推荐
4. SSH 架构中 Illegal attempt to associate a collection with two open sessions 问题 。 解决方法:使用 Hibernate 的 merge 方法代替 save、update 等方法。merge 方法可以把对象转变为托管状态的对象,而 ...
在使用C#与南大通用数据库(GBase)交互时,遇到的一个常见问题是尝试更新Blob或Clob(大型对象)时出现错误:“Illegal attempt to use Text/Byte host variable”。这个问题通常发生在利用CSDK中的ADO.NET驱动进行...
illegal access to protected memory(解决方案).md
在Java开发过程中,有时会遇到“illegal key size”这样的错误,这通常是由于Java加密相关的安全限制所导致的。这个问题在 JDK 7 版本中尤为常见,因为默认配置的Java Cryptography Extension (JCE) 有对密钥长度的...
今日遇到如下错误:java.security.InvalidKeyException: Illegal key size 因为美国法律限制,JAVA默认支持AES 128 Bit 的key, 如果你计划使用 192 Bit 或者 256 Bit key, java complier 会抛出 Illegal key size ...
在使用高版本版KEIL时,提示要升级固件,升级后就出现JLINK is Clone的...解决方案: 1.升级压缩包里的固件(该固件将SN修改为默认的-1)。 2.进入J-Link Commander,输入exec setsn=XXXXXXXX (XXXXXXXX为你新的SN号)
illegal opcode(解决方案).md
在Java编程环境中,有时会遇到一个常见的错误:"java.security.InvalidKeyException: Illegal key size"。这个错误通常是由于Java安全策略的限制导致的,尤其是当你尝试使用超过默认限制的密钥长度(例如,超过128位...
在Java编程中,`java.security.InvalidKeyException: Illegal key size` 是一个常见的错误,通常出现在加密或解密操作中,尤其是涉及到对称加密算法如AES(高级加密标准)时。这个错误表明您试图使用的密钥长度不受...
"illegal opcode 红屏报错(hp 360 G6安装win2021)问题解决方法" illegal opcode 错误是指在计算机启动过程中出现的致命错误,常见于操作系统安装或升级过程中。该错误会导致计算机无法启动,出现红屏报错。 ...
Copy the file with .scr extension to your computers win directory (Windows for 98, Winnt for NT) and check in screens saver settings.<END><br>73,Cls_sample_Collection.zip Implement with Class and ...
解决办法。 如在加密过程中出现下面异常: java.security.InvalidKeyException:illegal Key Size 请将两个jar文件按下列操作完成: 如果安装了JRE,将两个jar文件放到%JRE_HOME%\lib\security目录下覆盖原来的文件;...
google或者baidu一下,好多这样的问题,解决的方法都是修改php.ini,把allow_url_fopen给启用,改成 allow_url_fopen = On 这样做可以解决某些人的问题,有人说在php.ini中,有这样两个选项:allow_url_fopen =on...
Illegal Instruction(解决方案).md
对于`java.security.InvalidKeyException: Illegal key size or default parameter`这个异常,主要原因是Java默认的安全策略限制了密钥的长度,解决方法是下载并安装JCE Unlimited Strength Jurisdiction Policy ...
illegal function pointer(解决方案).md
illegal memory access(解决方案).md
[] 匹配中括号里的内容[a-z][A-Z][0-9]。 ! 事件。 $ 取环境变量的值。 | 管道。把前一命令的输出作为后一命令的输入,把几个命令连接起来。 |经常跟tee连用,tee 把内容保存到文档并显示出来。 三、通用后...
Chapter 23 that implement part of the RSA cipher would be illegal to export out of the United States. Because messages encrypted with RSA are impossible to hack, the export of encryption software like...
ArrayIndexOutOfBoundException is thrown when we have to indicate that an array has been accessed with an illegal index. printStackTrace in jsp printStackTrace is a method of the Throwable class. By ...