I have an entity that has a Set of child entities. Can I add/remove some of the children in the collection in Hibernate's org.hibernate.Interceptor.onFlushDirty()?
The documentation (javadoc, JBoss userguide) doesn't explicitly mention changing relationship state, so I just want to make sure it's legitimate.
Update
Decided to describe by problem.
There's a Parent entity that has a Set of Child entities. The Child entities are created based purely on fields of the Parent entity, no additional information needed. The children need to be updated each time before persisting the Parent.
I wanted to do it in Interceptor.onFlushDirty() by clearing existing children and adding new reclaculated (i.e. Transient) children, but I'm getting the TransientObjectException. As I understand, it's because I add transient Child entities during flush, but I'm not sure.
Related
TL;DR: Is it enough to call repository.save() on the owning entity to persist the relationship or do I need to save both entities?
Let's say I have two entities, A and B and a oneToMany relationship between them. A can have multiple B's, B can have an A. B is the owning side of the relationship (has the foreign key). If I have two, already persisted entities and want to add and persist a relationship between them, then I typically do this:
a.addB(b);
b.setA(a);
bRepository.save(b);
My question is, do I also need to call aRepository.save(a)? Thanks in advance, Googling didn't help me to find the answer.
If as you describe the relationship is owned by B, A didn't change at all as far as JPA is concerned. So it doesn't need to get persisted.
If you have persisted or loaded A and B in the current session, no save at all is technically necessary. JPA keeps track of the entities, note that they are changed and will flush the changes to the database at the end of the transaction.
Good question and assuming that you have already saved the A entity the answer should be that you do NOT need to save the parent A entity again since you have added the child entity B to A's list of children yourself and A is already persisted.
If you ever reload A and all its children you should get the same list as you currently have.
Since it is lazy loaded your query should specifically load the children in the case you want that otherwise you might get into the situation where you assume that A has all its children but you doesn't if you reloaded A from the database without getting them.
In general though I have to question why you are keeping A around in the first place. Caching can be a good thing but your cache should refresh A when its children are updated and should fetch all of A's children if that is what is needed. In that case you don't need to add the new child to A yourself b/c it will be overwritten anyway. Probably doesn't hurt, but why do you want to second guess the cache?
More generally the pattern is simply to save B and be done with it. If your code needs A and all its children it should fetch from the database when needed.
These thoughts do not include JPAs entity cache since I have not attempted to get into very specific detail about that.
In a one to many bidirectional association with cascade enabled as all-delete-orphan in hibernate, is there any possibility ever hibernate try to delete child entity using foreign key column?
Its firing one extra query delete from child where foreign_key_col = parent_primary_key.
For bidirectional relation,if you delete casacade in the parent entity.
You can remove the child from parent directly.
//set parent as null
child.setParent(null)
//parent.children.iterater and remove it from the iterator.
//then save the parent.
save(parent)
What are the various types of association in ORM and how do we manage the partial changes to a parent objects without modifying the child objects ?
I have an entity(ex: Document) that is used as child in 4 other entities(using #OneToMany with #JoinTable in parents). I am not using Bidirectional Mapping. My requirement is to remove the Child(i.e Document), and I have two ways to do that, one way is, get the 4 parents, remove child from them and update them. Second, using native query(using jdbcTemplate) to remove entry from 4 join tables and remove the child.
Is there any other way it can be done in much simpler manner?
Create an abstract base class containing the Document as member and user JPA inhertiance --> http://en.wikibooks.org/wiki/Java_Persistence/Inheritance
Than it should be possible to get all users of a document with just one query.
Than it should be relatively easy to remove all references.
Don't do magic behind automatic deletion stuff. Thats for the cost of documentation.
Add orphan deletion (ie. delete child object when it's removed from collection in the parent). To enable it, you need to add
#OneToMany(orphanRemoval=true)
in owning entity.
Given:
Two custom classes in Magento with a Many-to-One relationship between them.
The child holds a foreign key to the parent.
The database is set to cascade deletes.
There are cases when a child's reference changes to a different parent. In some of those cases, I want to delete the parent in the afterSave method of the child. When I do this, the child itself disappears, since the change of FK to the new parent hasn't been written to the database yet, and the database level cascade kicks in.
How can I arrange for the deletion of the parent object after the write of the new foreign key in the child object?
afterSave triggers before the query has been written to DB, as you've noticed yourself. You need to use *_save_commit_after event. Where asterisk is your Models event_prefix. Create an Observer and listen for this event, that way you can be sure that info in DB has been already updated, and you won't suffer the foreign key effect.