1

Lets say I have bidirectional one-to-many association between Parent-Child, mapped as follows:

Parent.java:

@Entity
public class Parent {

    @Id
    private Integer id;

    @OneToMany(mappedBy = "parent")
    private List<Child> childs = new ArrayList<>();
    ...

and Child.java:

@Entity
public class Child {

    @Id
    private Integer id;

    @ManyToOne
    @JoinColumn(name = "parent_id")
    private Parent parent;

    ...

When I run this code

    Parent parent = new Parent(1);
    Child child = new Child(1);
    Child child2 = new Child(2);
    child.setParent(parent);
    child2.setParent(parent);
    parent.getChilds().add(child);
    parent.getChilds().add(child2);

    parentRepository.save(parent);

I get exception

    Unable to find Child with id 1

Saving a child first doesn't help either, only exception is different

user3914074
  • 11
  • 1
  • 4
  • Well, some clarification here: – user3914074 Sep 18 '14 at 13:36
  • I need to save parent without saving childs, that is why no cascade is needed. Transient is not a solution in my case, I still want childs to be eagerly loaded on parent load. So without cascade, Spring JPA (or hibernate persistence provider, not sure which one is responsible) is checking every child's persistence. What is the point of this check if I will not save them anyway (or will save later)? – user3914074 Sep 18 '14 at 13:42
  • 1
    Why would you add children to a parent before persisting the parent, but not wanting to persist them too? - How about first persisting the parent and then, working with the persistent parent entity, add children as needed? When you're done, you `merge()` the new parent's state, including the children, into the DB. – JimmyB Sep 18 '14 at 13:49
  • That all because I don't have consistent sync with database, let's say my entities can change in time, and if I have parent with 1000 children, without cascade I simply check if child was changed (it has an extra boolean attribute for that) and save/merge only it. If I used cascade It would check every 1000 children by requesting database (and I'm not talking about other relations there), and that is a LOT of database requests! – user3914074 Sep 19 '14 at 08:53
  • 1
    I think this is only partially true. As long as you are using a single persistence context and don't detach the persistent entities from it the objects are "attached" to it. This means that the context will be able (through proxy objects or instrumentation) to determine exactly which property of which of the persistent object(s) has changed since the last sync with the DB and persist/merge only those, without an additional round-trip to the DB. This basically means that the persistence provider already manages and uses an internal flag for you to note which objects are "dirty" w.r.t. the DB. – JimmyB Sep 19 '14 at 10:28
  • "Saving a child first doesn't help either, only exception is different" - Or maybe try to persist child, persist parent, add child to parent, set child's parent, merge child, merge parent. Somewhat clumsy, even if it works. – JimmyB Sep 19 '14 at 10:35

2 Answers2

0

well i am sorry for posting a not sure answer but i cannot post a comment cause of reputation. i think you have a cross reference problem, because simply by referencing the parent from the child you can get the childs that parent has with a simple query. instead you cross reference the child association resulting to many object problems. if you want i can post you a class diagram for better explanation. hope it helps

AntJavaDev
  • 1,204
  • 1
  • 18
  • 24
  • No, that is a completely correct bidirectional association (am I wrong?). – user3914074 Sep 18 '14 at 13:35
  • lets say its ok , and try to think simple use cases. 1st case : you want to add a parent with null children list , which will work and 2nd case : you want to add a children with null parent which will work too and , now in your posted case you are initializing a parent object , reference it with 2 children and then you try to save the parent with unsaved children entities so hibernate cannot find them same as the opposite case in which you first try to save the children with an unsaved parent reference – AntJavaDev Sep 18 '14 at 14:24
  • So, what we have is: Bidirectional association will never work without cascading? – user3914074 Sep 19 '14 at 08:47
  • you can do it without cascading if you follow Hanno Binder's solution as he posted it in the comment above – AntJavaDev Sep 19 '14 at 09:49
0

Try

@OneToMany(mappedBy = "parent", cascade={CascadeType.PERSIST})
private List<Child> childs = new ArrayList<>();

(see also JPA @ManyToOne with CascadeType.ALL for example)

Community
  • 1
  • 1
JimmyB
  • 12,101
  • 2
  • 28
  • 44