|
Here is another closely related issue:
// Get a theme Theme theme = DefaultTheme.getRoot(session); // Get a child theme Theme childTheme = (Theme) theme.getChildren().iterator().next(); // Evict it Serializable id = session.getIdentifier(childTheme); session.evict(childTheme); // Reload the child childTheme = (Theme) session.get(childTheme.getClass(), id); // This throws: org.hibernate.NonUniqueObjectException: a different object // with the same identifier value was already associated with the session // because the parent is still pointing to the old child. At flushing time, // it cascades saveOrUpdate() on the old child but the session already has // the new child (with the same id) associated with the session. session.flush(); Please consider increasing the priority of this issue as it makes it impossible to use long-term sessions for manipulating large objects. There doesn't seem to be a safe way to evict them from the session after they are used (to prevent OutOfMemoryError) and then reload them at a later time when they are referenced again. +1
Please, consider this one. For EJB 3.0 this is failing due to a listener and and clear() is not called for the EntityManager. We must track changes to an entity, so in the pre-update callback we store a copy of the current entity and refresh it to get the old values. When I restore the updated state and let the flush() process continue this exception is raised. I cannot evict() the parent object because it still has to be saved and there is no such method in EntityManager.
Patch against Hibernate 3.1.3
Apply it with: patch -p1 -i ./reattach-same-session.patch I developed this patch to fix two problems I faced when reattaching objects to the session after clearing it: - "reassociated object has dirty collection reference" - "Found two representations of same collection: (collection type)" This patch fixes this problem by allowing an object from a given session to be reattached. To do that, there are two minor changes in two classes: - OnLockVisitor: in processCollection(), when a collection has been attached to the same session, we only throw an exception if the collection is dirty, otherwise we reattach this collection to the session and move on. - Collections: in processReachableCollection() method, when a given collection is not found in the session persistence context, we check if it is a collection that has been previously attached to the session. If it is, we add this collection back to the persistence context. That fixes "Found two representations..." problem. This code was tested and works just fine for me, fixing the problems I was facing. I hope this patch helps to solve the problems mentioned above. PLEASE, check if this is the correct solution and review this code, in this case. I am not an expert in hibernate source code, so maybe there are other scenarios that reattaching objects is not allowed. - Background Some background of why I needed this problem fixed. Basically, I have a web application (spring mvc + hibernate) and wanted to develop JUnit tests for it. Using AbstractTransactionalSpringContextTests Spring class, each method is transactional, rolling back after its completion as a default behavior. However, my goal was simulate several requests in a given method, ie, within a transaction (which happens to be per method). For that, everything would be perfect if I could clear hibernate session, in order to test the scenario where I have LazyInitializationException and similar problems: public void testMethod1() throws Exception { // request1 request = new MockHttpServletRequest(); getCurrentSession().clear(); // .. request code ... // request2 request = new MockHttpServletRequest(); getCurrentSession().clear(); // requestN request = new MockHttpServletRequest(); getCurrentSession().clear(); } But I had to implement thousands of workaround to avoid the problems mentioned above, what is impossible to maintain in the long run. Does any one know if this patch was made in the new version of hibernate? Thanks
Danny: if you'd like to have this patch included in your application, but you don't want to supply a patched recompiled version of hibernate, you could simply include those two patched files this patch affects in your classpath before the hibernate jar, ant the classloader will use the patched version of the classes. Later, when the bug gets fixed in a future release of hibernate you can simply remove the patched classes and switch to the new hibernate jar.
Fixed some problems with previous patch. This version is on my production and development server.
Hibernate version: 3.1.3
Hi, I thinks this issue is related to another one: When occurs an exception in a transactional method, the Hibernate session associated seems to be cleared, then when is executed another method with the same session and it tries to save an object that was in the session after the exception ocurrencie, the following exception is triggered: "org.springframework.orm.hibernate3.HibernateSystemException: Found two representations of same collection: org.appfuse.model.User.roles; nested exception is org.hibernate.HibernateException: Found two representations of same collection: <<collectionName>> " For example: BeanA method { User u = UserDao.getUser(1l); for (int i=0;i<=1;i++) { try { beanB.transactionalMethod(u); }catch (RuntimeException e) { System.err.println("RuntimeException ="+e);} } } BeanB transactionalMethod(User u) { ... userDao.save(u); } Assuming that BeanA.method and BeanB.transactionalMethod are transactional and they are using the same Hibernate session, if an exception is triggered in the first call to transactionalMethod, then in the second call that method an exception will be triggered in userDao.save(u). This exception is the commented above, and it happens because in the first method the hibernate session is cleared at the moment of the rollback, so it seems to have no entities and collections associated, but the exceptions is telling us another thing. This seems contradictory and it looks like Hibernate is not handling correctly this situation. I was able to avoid this exeptions using session.refresh(u) before saving the user object, but I think that Hibernate should be handling this transparently. Thanks. What is the current state of this bug?
I think the priority should be raised at least to major, because the needed workarounds are really ugly. What about the patch? Can it be applied into a new hibernate version? I have the scenario above: The first transactional method throws an exception and the transaction is therefor rollbacked causing a clear() on the session. The following updates do not work anymore with the famous error message: Found two representations of same collection... I use Spring with a HibernateInterceptor so I just cannot throw the session away and create a new one. I solved the problem with a call to Session.merge() before update(), but this solution is ugly because merge() creates a new persistent instance, so I have to replace all references to the old detached instance with the new attached persistent instance. Unlike the scenario above I cannot use refresh() because it overwrites the current state with the state from the db discarding all changes. as i understand patch is against hibernate 3.1
but we already work with 3.2 this is most voted bug in hibernate3 ... Rodrigo, thanks for the patch. Initially I am inclined to think that the correct solution is to simply "unset" the session references for collections and proxies during clear (currently, they are simply removed from the session's persistence context, but their session reference is never cleared). Perhaps a better solution is to basically run evict() on all persistence context entries since evict does all of this work already.
Could you include test cases for all the scenarios you saw failing? Markus, regardless of what you want to do or dont want to do, throwing away the session is the only supported means for exception handling.
Reported issue fixed on trunk / 3.2
This fix generated a problem on session.clear() performance, as posted on the forum:
http://forum.hibernate.org/viewtopic.php?t=990508 I've tested Rodrigo Castro patch with good results. Patch for this fix probably generates
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Load load = new Load();
load.setStartTime(new Timestamp(System.currentTimeMillis()));
load.setType("xxx");
load.setStatus("xxx");
load.addMessage("xxx");
session.save(load);
session.flush();
session.evict(load);
load.addMessage("yyy");
session.update(load);
session.flush();