Reputation: 1317
I have 3 entity: 'Person', 'Document', 'PersonDocument' which related as following:
class Person {
@Cascade(CascadeType.ALL)
@OneToMany(mappedBy = "person", orphanRemoval = true, fetch = FetchType.LAZY)
Set<PersonDocument> personDocuments;
}
class Document {
@OneToMany(mappedBy = "document")
Set<PersonDocument> personDocuments;
}
@IdClass(PersonDocumentPK.class)
public class PersonDocument {
@Id
private Person person;
@Id
private Document document;
@ManyToOne(fetch = FetchType.LAZY)
private Provider provider;
}
public class PersonDocumentPK implements Serializable {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "person_guid")
private Person person;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "documents_guid")
private Document document;
}
In my code I am trying to delete some records from Person#personDocuments
and add new records. I am doing it like:
Iterator it = person.getPersonDocuments().iterator();
PersonDocument pd = it.next();
if (some logic) it.remove();
...
person.getPersonDocuments().addAll(new set of values);
In result removed personDocuments
have disappeard, but related documents
remained on database. Why is so?
Upvotes: 1
Views: 2132
Reputation: 245
Cascade operations doesn't work like that.
When you use the @Cascade
annotation, operations made in the parent will cascade to child assossiations depending on the cascade type.
As your class is annotated with CascadeType.ALL
, all operations made in the parent class will cascade to the childs.
So, for the remove to work, you would need to call entityManager.remove(person)
, and then the persistence provider would call the remove in the childs too.
That being said, change your code to somethng like that:
Iterator it = person.getPersonDocuments().iterator();
PersonDocument pd = it.next();
if (some logic) {
it.remove();
em.remove(pd); // No problem to call in the loop because it will call the database only on commit or flush
}
...
person.getPersonDocuments().addAll(new set of values);
Upvotes: 1
Reputation: 2423
try CascadeType.DELETE instead of CascadeType.ALL
@Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE})
Upvotes: 0