相关问题及解决办法:
FYI, if you perform the update() of the object in a subsequent session, the update will work correctly. It only errs out when you do the update() in the same session in which you have performed a clear() operation.
I've looked through the SessionImpl, but I'm not yet familiar with the code base and can't figure out why the error is being issued. But I strongly feel that this should not be an error condition.
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
Code between sessionFactory.openSession() and session.close():
Code:
Load load = new Load();
load.setStartTime(new Timestamp(System.currentTimeMillis()));
load.setType("xxx");
load.setStatus("xxx");
load.addMessage("xxx");
session.save.save(load);
session.flush();
session.clear();
load.addMessage("yyy");
session.update(load);
session.flush();
Full stack trace of any exception that occurs:
Code:
com.everstream.s4.database.TransactionException: net.sf.hibernate.HibernateException: Found two representations of same collection: com.everstream.idg.data.Load.messages
at com.everstream.s4.database.Transaction.completeTransaction(Transaction.java:345)
at com.everstream.s4.database.Transaction.commit(Transaction.java:110)
at com.everstream.idg.common.Main.test(Main.java:86)
at com.everstream.idg.common.Main.main(Main.java:39)
Caused by: net.sf.hibernate.HibernateException: Found two representations of same collection: com.everstream.idg.data.Load.messages
at net.sf.hibernate.impl.SessionImpl.updateReachableCollection(SessionImpl.java:2870)
at net.sf.hibernate.impl.FlushVisitor.processCollection(FlushVisitor.java:32)
at net.sf.hibernate.impl.AbstractVisitor.processValue(AbstractVisitor.java:69)
at net.sf.hibernate.impl.AbstractVisitor.processValues(AbstractVisitor.java:36)
at net.sf.hibernate.impl.SessionImpl.flushEntity(SessionImpl.java:2592)
at net.sf.hibernate.impl.SessionImpl.flushEntities(SessionImpl.java:2458)
at net.sf.hibernate.impl.SessionImpl.flushEverything(SessionImpl.java:2260)
at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2239)
at net.sf.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:61)
at com.everstream.s4.database.Transaction$SessionResource.commit(Transaction.java:367)
at com.everstream.s4.database.Transaction.completeTransaction(Transaction.java:304)
... 3 more
Exception in thread "main"
I'm running into the same problem. Is this a bug? Calling Session.clear() should clear all objects out of the Session, correct? So, why is it finding and complaining about a duplicate collection?
解决办法: After letting this problem sit for a while, I found a workaround. I still believe the test case demonstrates a real (if minor) defect with Hibernate, but there is a simple workaround.
The problem is due to the session "seeing" the same collection twice in the same session (which happens when you update() the collection-containing object after clearing the session). So, the solution is to replace the original collection with a new collection:
This will cause some extra updates, but it's a very small price to pay in my case. (I'm inserting upwards of 5 million records into the database in a single transaction, which is why I have to clear() the session periodically in the first place.)
Hope someone else may get benefit from this solution.
The exception can happen (at least) in such case that:
- Your object have Set field, and
- your code does session.update() after session.clear() //This is the key point
(Sorry, I do not know why Hibernate cannot handle this case better)
So, you can for example solve the problem by
- avoid the above case, or
- after session clear, do session.load() to load a clean object again, or
- close the session after session.update(), then you need to open a new session()
I do not justify these quick solutions well. So, you need to do this by yourself. There are probably some other (better) solutions.
I was running into the caching issue too. I have a HibernateUtility class that handles Hibernate sessions for threads using ThreadLocal variables. Since my server opens a bunch of threads, then leaves them open to service future requests, the cache for one thread would be updated, but all other threads would have old data. As a temporary fix, I added a clear(); to the HibernateUtility class to clear the session every time it was retrieved. That's when I ran into the problem described here (call to update() after call to clear() produces an error). I fixed this by passing the HttpServetRequest into the HibernateUtility class and storing its hash in a ThreadLocal variable. If a session is retrieved twice in the same request, it is only cleared the first time. This may not be the best way, but it's easy and it works!
===========================================
问题好像出在我修改教师信息的功能上,当我修改教师时,出现a different object with the same identifier value was already associated with the session,因此我使用了session.clear(),这个异常问题解决了,但是上述问题就出现了,查了一些资料,问题就是因为我session.clear()引起的。
请问我该怎么解决这个问题?
谢谢大家!