Say you have a unidirectional one-to-many association from class A to class B, like this:
public class A {
@OneToMany(cascade = CascadeType.ALL)
private List<B> myBs;
}
public class B {
//I know nothing about A
}
In the database, these are connected through a third table, keeping their id's.
Now, I would like to delete a B-object, that is connected to an A. A has its own repository class, and B has its own repository class.
The way this has been done in similar settings in my project, is to first ask the A in question to remove the B in question, and then telling the EnitityManager
to remove the B from the database.
This makes me a bit stuck between two choices, where neither of them are optimal in my mind:
The repository method in BRepository
handles both the removal of B from the A its connected to, and the removal from the database through the EntityManager
. I don't like this, because then B's repository-class will have to manipulate A-objects.
The repository method in BRepository only deals with removal through the EntityManager, leaving it up to the caller to remove it from A's collection. I like this even less, because if someone were to call the repository without first removing the B from A's collection, it will fail horribly.
Of the two I find the first to be by far the best. But still, I don't really think that it's clean.
Is there some construct in Hibernate that allows for the item to be deleted to be removed from any collection it is part of, upon removal from the database? (Trying to just delete the B fails because the A containing it is also loaded in the same transaction, so it fails upon the end of the transaction, when it's trying to store something that is deleted.)
(Would adding mappedBy
on the @OneToMany-mapping
in A solve the problem?)
I've found a way to solve this, through the use of orphan deletion.
By changing the mapping in A to this:
public class A {
@OneToMany(cascade = CascadeType.ALL)
@Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
private List<B> myBs;
}
I can just say
a.getMyBs().remove(b);
and b
will be deleted upon a
being persisted.