I thought I had a better understanding of Spring Data JPA (deletes) until recently.
Anyway, I have two classes with a OneToMany
and a ManyToOne
relationship:
@Entity
@Table(name = "COMPANIES")
public class Company implements Serializable {
...
@OneToMany(mappedBy = "company",
fetch = FetchType.EAGER,
orphanRemoval = true,
cascade = CascadeType.ALL)
private Set<Commodity> commodities = new HashSet<>();
}
....
@Entity
@Table(name = "COMMODITIES")
public class Commodity implements Serializable {
...
@ManyToOne(optional = false)
@JoinColumn(name = "COMPANY_ID", referencedColumnName = "ID", nullable = false)
private Company company;
}
I want to delete a Commodity
record so I have this in my service layer:
@Transactional
public void delete(Commodity commodity) {
repo.delete(commodity);
}
When I run the code, it performs all of the SELECT's but it never actually performs the delete. No error messages...no delete in the logs, etc.
So I found I have two options:
1) Remove the CascadeType.ALL
2) Change my delete method to:
@Transactional
public void delete(Commodity commodity) {
Company company = commodity.getCompany();
company.getCommodities().remove(commodity);
companyRepo.save(company);
}
3) Write a custom @Query method to perform delete (rather not).
My understanding of the cascading was that if we were to delete a master record like Company, then all of its child objects would be automatically deleted. That makes sense to me.
So, my question is, why does that CascadeType prevent me from manually deleting a child record?
Thanks
EDIT
I wasn't very clear. Using option 1 or option 2 above does perform the delete.
This is by design.
When you try to remove a commodity by itself, the owning entity still has record that an instance of a commodity should still exist in the database.
Here is the exact quote from the hibernate doc: