I have 1-N relationship (object has a list) and want remove one item from the list. What is the right way of removing item in the list开发者_JAVA百科 with JPA?
Do I have to first update the list and merge the owner and remove the item after (if I do not remove the item and just merge the owner, orphan will remain in DB, right)? In what sequence should be merge() and remove() called, does the order of remove() and merge() matter?
Code sample:
List<Item> items = owner.getItems();
Item itemToRemove = items.get(index);
owner.remove(itemToRemove);
em.merge(owner);
em.remove(itemToRemove);
This should work in case you have orphanRemoval=true
(JPA 2.0).
For JPA 1 there is no standard way to handle this. Hibernate has @Cascade
where you can specify DELETE_ORPHAN
This is sufficient:
List<Item> items = owner.getItems();
Item itemToRemove = items.get(index);
items.remove(itemToRemove);
When the EntityManager
is flushed, the link between owner
and itemToRemove
will be deleted. And if cascade
is set to CascadeType.ALL
, itemToRemove will also be deleted.
Actually, a shorter (and equivalent) version is this:
List<Item> items = owner.getItems();
// no need to keep a reference to the object that has to be removed
items.remove(index);
Reference:
- Managing Entities (Java EE 5 tutorial)
[unfortunately there is no passage where this is written out explicitly, you have to read between the lines a bit]
Thank you guys for the answers. Your answers are very similar but there are some slight differences.
Just want to make sure that I understand it right:
- In JPA 1.0 (in general) I have to call remove() on referenced entities. They won't be removed with flush of entity manager. Otherwise orphan would remain in DB.
- In JPA 1.0 with Hibernate implementation when DELETE_ORPHAN set, referenced entity is removed with flush of entity manager. No need to call remove().
- In JPA 2.0 (in general) when orphanRemoval=true, referenced entity is removed with flush of entity manager. No need to call remove(). If orphanRemoval is not set, remove() has to be called to remove referenced entity.
Normally, you don't have to do anything like that.
If the collection is properly mapped, you should call items.remove(itemToRemove) and that is all.
When you close the EntityManager (this triggers writing changes to the database), it should automatically recognize that the item has been removed (orphaned) from owner and delete it from the database. At least Hibernate works this way and one can specify DELETE_ORPHAN as a cascade on the mapping of the collection.
精彩评论