I have a parent object Compound with a one-to-many relationship to an object Submission. I have set up the relationship as follows:
@Entity
public class Compound implements Serializable {
@Id
private long compoundId;
...
@OneToMany(mappedBy="compound", fetch=FetchType.LAZY,
cascade={ CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.REMOVE })
@PrivateOwned
private List<Submission> submissions;
...
}
@Entity
public class Submission implements Serializable {
@Id
private long submissionId;
...
@ManyToOne(fetch=FetchType.LAZY,
cascade={ CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.REMOVE })
@JoinColumn(name="compoundId")
private Compound compound;
...
}
I have set-up a form (in Flex) to modify a selected Compound. Given the form output (a BlazeDS class called ObjectProxy, which extends HashMap) I map the values from the form onto a new Compound object. The submissions data is not stored in the form hence the submissions list on the new Compound object remains null.
public Compound decodeWebForm(final ObjectProxy proxy) {
// create a new compound object
final Compound c = new Compound();
// map the proxy values onto the new compound
c.setCompoundId(proxy.get("compoundId"));
...
return updateCompound(c);
}
Next I merge the Compound object I have constructed into the persistence context.
public Compound updateCompound(final Compound c) {
// retrieve the entity manager
final EntityManager em = getEntityManager();
// begin a transaction
em.getTransaction().begin();
// merge changes to the managed compound
final Compound managed = em.merge(c);
// commit changes to the database
em.getTransaction().commit();
return managed;
}
I have specifically omitted the CascadeType.MERGE directive from the relationship definitions. As such, when I call the EntityManager.merge(Compound) method I was expecting the lack of submissions data to be ignored. However, this is not the case and any submissions relating to the Compound I am modifying are deleted.
I must be doing something wrong or have misunderstood the meaning of CascadeType.MERGE? Can someone please help?
Thanks
James
Two problems:
1) You marked the relationship with @PrivateOwned which should cause all dereferenced entities to also be deleted.
2) you are merging an empty collection. Cascade merge (or the lack there of) only means that the merge will (or will not be) cascaded to the Submissions entities. The state of the collection itself though is considered part of the Compound and so needs to be updated in the database. Coupled with #1, this means that Submissions will be deleted. IF not for #1, there would be no change in the database (since Submissions own the relationhip and haven’t changed), but when reading back the Compound entity, it will show a null or empty collection unless it gets refreshed.
Creating a new instance of the entity is a bad idea. Instead, you might want to read it in and only change what is needed from the form – then merge this entity into the transactional context if required.