开发者

Force transitive persistence order in JPA 2 w/Hibernate?

开发者 https://www.devze.com 2023-04-03 12:52 出处:网络
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 ca

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消