I currently have a setup similar to:
@MappedSuperclass
public abstract class AbstractEntity implements Serializable {
private Long id;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
@Entity
public class Container extends AbstractEntity {
private Collection<Item> items = new HashSet<>();
@Cascade(CascadeType.SAVE_UPDATE)
@OneToMany(mappedBy = "container", orphanRemoval = true)
public Collection<Item> getItems() { return items; }
public void setItems(Collection<Item> items) { this.items = items; }
}
@Entity
public class Item extends AbstractEntity {
private Container container;
@ManyToOne(optional = false)
public Container getContainer() { return container; }
public void setContainer(Container container) { this.container = container; }
}
@Entity
public class FirstItemDetails extends AbstractEntity {
private Item item;
@OneToOne(optional = false)
@Cascade({CascadeType.DELETE, CascadeType.REMOVE})
public Item getItem() { return item; }
public void setItem(Item item) { this.item = item; }
}
@Entity
public class SecondItemDetails extends AbstractEntity {
private Item item;
@OneToOne(optional = false)
@Cascade({CascadeType.DELETE, CascadeType.REMOVE})
public Item getItem() { return item; }
public void setItem(Item item) { this.item = item; }
}
I've left out some of the unnecessary fields as they make no difference in the end. Now for the problem. What I want to do is something like:
public void removeItemFromContainer(Item item, Container container) {
Transaction transaction = session.beginTransaction();
container.getItems().remove(item);
session.save(container);
transaction.commit();
}
What I expect from this function is to physically remove the item from a given container and since I have orphanRemoval set to true, when I persist my container it does actually try to remove the item from database. The problem here lies with the ItemDetails entity which has a foreign_key constraint so when the commit is being ran I get:
org.hibernate.exception.ConstraintViolationException: could not execute statement
Caused by: java.sql.SQLIntegrityConstraintViolationException: integrity constraint violation: foreign key no action; FK_FITEM_DETAILS_ITEM table: first_item_details
Caused by: org.hsqldb.HsqlException: integrity constraint violation: foreign key no action; FK_FITEM_DETAILS_ITEM table: first_item_details
The most confusing part to me is that when I physically add ON DELETE CASCADE in first_item_details table in database rather than relying on hibernate to cascade for me, everything works. But this approach is error prone because if at some point I'll decide to use an interceptor or eventListener for my any of my details entity it simply won't work so I'd much prefer to allow hibernate to handle it rather than needing to rely on manual db structure change.