Yichz
Yichz

Reputation: 9681

JPA Hibernate one to many batch insert

conside this scenario:

    class Parent {
     private Integer id;
     private String name;
     @oneToMany(mappedBy="father")
     private List<Child> children;
     ... ...
    }

    class Child {
     private Integer id;
     private String name;
     @ManyToOne (optional="false")
     @JoinColumn(name="id")
     private Parent father;
     ........
}


Class MyParentService{

     public Parent parentService(List<Child> childList){
        em.getTransaction.begin();
        Parent parent = new Parent();
        parent.setChildren(childList);
        em.persist(parent);
        em.getTransaction.commit();
   }
}

I will get an Exception of org.hibernate.PropertyValueException: not-null property references a null or transient

because the attribute father is "optional=false"

so I have to replace parent.setChildren(childList); and do a loop like this in parentService() :

for(Child c: childList){
 c.setFather(parent.getId());
 parent.getChildrent().add(c);
}

is this correct? is there a better way to do without looping childList again?

Upvotes: 2

Views: 3591

Answers (2)

axtavt
axtavt

Reputation: 242786

When working with Hibernate, it's your responsibility to maintain consistent state of both sides of bidirectional relationship. Moreover, when persisting a relationship, Hibernate looks at the owning side (the side without mappedBy), so you code wouldn't be correct even without optional=false.

You can use the following approach to ensure consistensy:

class Parent {
    ...
    public void addChild(Child c) {
        children.add(c);
        c.setParent(this);
    }
}

public Parent parentService(List<Child> childList) {
    ...
    for (Child c: childList) {
        parent.addChild(c);
    }
    ...
} 

In this case visibility of setChildren() can be restricted to avoid erroneous calls.

Aslo, it looks strange that you don't have cascading and don't persist children inside the same transaction with the parent.

Upvotes: 4

kan
kan

Reputation: 28991

I think it's good thing to do - e.g. in unit tests you may not use hibernate which automagically could set "father", but code should still work.

Upvotes: 0

Related Questions