[
http://opensource.atlassian.com/projects/hibernate/browse/HHH-3332?page=c...
]
Trond Isaksen commented on HHH-3332:
------------------------------------
I believe the problem is that when merging from a child C1 to a parent P, the cascade is
done BEFORE the save, which means that the parent will actually do a cascade back to the
child C1 first, which will then be inserted. After the parent has been processed, the
first C1 merge()-call will insert the child again. I believe that exchanging the
DefaultMergeEventListener with the following fixes the problem:
public class ModifiedIdTransferringMergeEventListener extends DefaultMergeEventListener {
private static final long serialVersionUID = 1L;
static ThreadLocal<IdentitySet> transientObjects = new
ThreadLocal<IdentitySet>();
/**
* Hibernate 3.1 implementation of ID transferral.
*/
protected void entityIsTransient(MergeEvent event, Map copyCache) {
boolean topLevelInvocation = transientObjects.get() == null;
if (topLevelInvocation) {
transientObjects.set(new IdentitySet());
}
if (transientObjects.get().contains(event.getEntity()))
return;
transientObjects.get().add(event.getEntity());
super.entityIsTransient(event, copyCache);
//Start IdUpdating
SessionImplementor session = event.getSession();
EntityPersister persister = session.getEntityPersister(event.getEntityName(),
event.getEntity());
// Extract id from merged copy (which is currently registered with Session).
Serializable id = persister.getIdentifier(event.getResult(),
session.getEntityMode());
// Set id on original object (which remains detached).
persister.setIdentifier(event.getOriginal(), id, session.getEntityMode());
//End IdUpdating
if (topLevelInvocation) {
transientObjects.get().clear();
transientObjects.set(null);
}
}
}
The transientObject threadlocal just remembers the objects that are going to be inserted,
and stop cascading from reaching them again. A better implementation would obviously be to
send the map with "inflight" objects as a parameter instead of using a
threadlocal. Please note that this implementation also contains the code from the
IdUpdatingMergeEventListener(Spring), which updates the id of merging objects as the merge
takes place. To me that is the only reasonable approach...but this can be easily changed
by removing those lines.
However, I am too concerned about potential side-effects to actually put this into
production, which means we are stuck with an approach with tedious and painful object
rearranging and decoupling-operations. Would be nice to have a comment from the official
team. :-)
Hibernate duplicate then child entity's on merge
------------------------------------------------
Key: HHH-3332
URL:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-3332
Project: Hibernate Core
Issue Type: Bug
Affects Versions: 3.2.6
Environment: JDK 1.6
Oracle 9i
Hibernate 3.2.6
Hibernate Annotations 3.3.1
Hibernate EntityManager 3.3.2
Standalone Running
Reporter: Rodrigo de Assumpção
Assignee: Gail Badner
Priority: Critical
Attachments: ExampleBug.zip
The method merge from EntityManager causes a duplication of child entity's.
class Father:
@OneToMany(mappedBy = "father", cascade={CascadeType.ALL},
fetch=FetchType.LAZY)
private List<Child> childList;
class Child:
@ManyToOne @JoinColumn(name = "ID_FATHER")
private Father father;
class BugTest
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("JpaTestHB");
EntityManager em = emf.createEntityManager();
Father f = (Father) em.createQuery("SELECT f FROM Father f WHERE f.id =
1").getSingleResult();
Child c = new Child();
c.setFather(f);
f.getChildList().add(c);
em.getTransaction().begin();
em.merge(f);
em.getTransaction().commit();
The execution of BugTest Class causes tow insert's on table "child".
If you change the fetch mode to EAGER (into Father class) the problem not occurs.
I make the same test with Toplink, and it make a unique insert, normal.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira