Is there any way to force the persistence order of objects in JPA 2 w/Hibernate?
Say I have three classes: Parent
, Child
, and Desk
. Parent
owns collections of Child
and Desk
via @OneToMany
; a Child
can have one Desk
. Furthermore, Parent
defines transitive persistence on both collections, but Child
does not define transitive persistence on its Desk
:
class Parent {
@OneToMany(cascade=CascadeType.ALL) Collection<Child> children;
@OneToMany(cascade=CascadeType.ALL) Collection<Desk> desks;
...
}
class Child {
@OneToOne(cascade={}) Desk desk;
@ManyToOne Parent parent;
}
class Desk {
@ManyToOne Parent parent;
}
Ideally, I'd like to create a Desk and a Child at the same time and persist the relationships:
Parent parent = em.find(...);
Child child = new Child();
Desk desk = new Desk();
// add both desk and child to parent collections here
// set Parent attribute on both desk and child
If I execute the above code in a transaction, Hibernate cascades from Parent
to its new Child
and attempts to persist the new Child
object. Unfortunately, this results in an "object references an unsaved transient instance" error, because the cascade from Parent
to Desk
hasn't resulted in the new Desk
object being persisted yet.
I know I can fix the problem with an EntityManager flush() operation (em.flush()
) - create the Child
, create the Desk
, attach both to Parent
, em.flush()
, then attach the 开发者_StackOverflow中文版Desk
to Child
, but I'm not super-keen on littering my code with em.flush()
to save complex graphs of new persistent objects. Is there a different way to signal to JPA 2 or Hibernate that it should always persist the new Desk
first instead of the new Child
?
Looking at your description, I think that the Persistence system tries to persist first in this order:
- First the Parent.children[i]
- Each Children[i] has a transient pointer to Desk. The system fails to persist it because you have not configured it as Cascade.Persist.
Then it fails when persisting Desk, and you think that it fails in the path Parent.desks[i] (which is configured as Cascade) but maybe the fail doesn't come from this path.
精彩评论