riteshg
riteshg

Reputation: 31

Entity with CascadeType.ALL in OneToMany not persisting children

I'm working with a 3rd party library provided to our team where one of the entities has a OneToMany relationship to entities of the same type of itself. I've changed the entity name to keep it anonymous.

Probably there's a better way of annotating entities with this type of relationship but as it's provided by a 3rd party I'm avoiding making to many changes so that it's compatible with future patches and updates.

It's using OpenJPA 2.4.0-ep2.0

@Entity
@Table(name =  Person.TABLE_NAME)
public class Person {
private Long parentUid;
private List<Person> children = new ArrayList<>();

@OneToMany(targetEntity = Person.class, cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
@ElementJoinColumn(name = "PARENT_UID")
@ElementForeignKey
@ElementDependent
public List<Person> getChildren() {
    return this.children;
}

}

When I try to persist a person with children, only the main entity gets persisted and children ignored.

However, if I change the fetch attribute to FetchType.EAGER it works (it persists both the parent and children). My understanding was that the fetch type only affects the loading, not the inserting. Any ideas why is it happening?

Also, is there a way of making it work while keeping the fetch type to FetchType.LAZY?

I've tried the following (modify the setter):

protected void setChildren(final List<Person> children) {
    if (Objects.nonNull(children)) {
        for (Person child : children) {
            child.setParentUid(parentUid);
        }
        this.childItems = children;
    } else  {
        this.childItems = new ArrayList<>();
    }
}

Upvotes: 1

Views: 1080

Answers (1)

reza ganji
reza ganji

Reputation: 11

Problem is in the child entity ,you should use @ManyToOne annotation in child entity.

add following code to Person :

public class Person {
  .
  .
    
  @ManyToOne(fetch=FetchType.LAZY)
  @JoinClolumn(name="PARENT_UID")
  private Person parent;
            
  public void setParent(Person parent){
  }
  .
  .
}

then revise setChildren Code like this:

 protected void setChildren(final List<Person> children) {
        if (Objects.nonNull(children)) {
            for (Person child : children) {
                child.setParent(this);
            }
            this.childItems = children;
        } else  {
            this.childItems = new ArrayList<>();
        }
    }

one important point is ،always fetch type must be sync in parent and child.

Upvotes: 0

Related Questions