Why can i remove elements of a bidirectional relation although only one side of the relation is managed in persistence context (Example I)? When i have an unidirectional Relationship that doesn’t work (see Example II). Why?
Entities:
@Entity
Class User {
...
@OneToMany(mappedBy = "user")
private List<Process> processes;
@OneToOne // Unidirectional
private C c;
...
@PreRemove
private void preRemove() {
for (Process p : processes) {
p.internalSetUser(null);
}
}
...
}
@Entity
Class Process {
...
@ManyToOne
private User user;
...
@PreRemove
protected void preRemove() {
if (this.user != null) {
user.internalRemoveProcess(this);
}
}
...
}
@Entity
Class C {
}
Example I:
// Create User u1 with Processes p1, p2
tx.start();
// Only u1 is manged in persistence context and no process
userFacade.delete(u1); // There following is called: >> em.remove(em.merge(u1)); // Works
tx.commit();
Example II:
// Create User u and Object C c, establish their relation.
tx.start();
cFacade.remove(c); //>>MySQLIntegrityConstraintViolationException,foreign key constraint fails
ty.commit();
In the first example i use these internal methods to set in each case the other side of the relation but this other side is not managed in persistence context i think?! When i change a process of a user and save the user, the process is not updated unless i uses cascade.MERGE or if both are loaded in a transaction and therefor are managed in pc. So why does the removing work?
In Example II, I guess you would have to call
user.setC(null)before deleting thec.In Example I, here is my understanding. You are first merging
u1so au1'gets loaded into the PC and the state ofu1is copied tou1'(and that’s all since you’re not cascadingMERGE), which is then returned. Then you call remove (onu1'), thepreRemovegets called and changesp1'andp2'. They are thus dirty and will get updated appropriately on flush (setting the FK toNULL), whileu1'will be deleted. And everything works.Just in case, here are the semantics of the merge operation from the JPA 2.0 specification:
Reference