Wojtek
Wojtek

Reputation: 67

Hibernate update/delete one to many collection

I have two classes Parent and Child with one to many relation.

Lets suppose that I have already persisted in my database structure like this:

Parent--> Child1, Child2

And than I get this new structure (with changes in Child1, without Child2 and with new Child3):

Parent--> Child1, ​Child3

So: Child1 should be updated, Child2 should be removed and Child3 should be added.

Unfortunately Hibernate with CasadeType.ALL and orphanRemoval=true only adds and updates, but don't delete automatically Child2. I need to compare list with entites to update and persisted one to look for objects to delete.

I wonder if there is any pattern that solves in elegant way my problem or maybe should I change some properties in Hibernate?

--- EDIT ---

Entities aren't anything fancy, something like this lets say:

@Entity
@Data
public class Parent {
   @Id
   @GeneratedValue(strategy = SEQUENCE)
   private long id;

   @OneToMany(mappedBy = "parent", casade = CasadeType.ALL, orphanRemoval = true)
   private Set<Child> childList;
}


@Entity
@Data
public class Child {
   @Id
   @GeneratedValue(strategy = SEQUENCE)
   private long id;

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

}

Upvotes: 2

Views: 2122

Answers (1)

Mansoor
Mansoor

Reputation: 1259

This is the pattern I follow:

    @Entity
    @Data
    public class Parent {
       @Id
       @GeneratedValue(strategy = SEQUENCE)
       private long id;

       @OneToMany(mappedBy = "parent", casade = CasadeType.ALL, orphanRemoval = true)
       private Set<Child> childList = new HashSet<>();
       
       public void addChild(Child child){

            if(child!=null){
              this.childList.add(child);
              child.setParent(this);   
            }
       }

       public void removeChild(Child child){

            if(child!=null){
              this.childList.remove(child);
              child.setParent(null);   
            }
       }

       public void updateChildren(Collection<Child> children){
           childList.forEach(x-> if(!children.contains(x)) this.removeChild(x); );
             
           children.forEach(x-> this.addChild(x));
       }
}

EDIT

You can create generic classes like this and use it. NOTE: THIS IS WAY COMPLEX TO IMPLEMENT

@MappedSuperClass
@Data
class Child<P extends Parent,C extends Child>{
        Parent<P,C> parent ;
}

@MappedSuperClass
@Data
class Parent<P extends Parent,C extends Child>{
    @Id
    @GeneratedValue(strategy = SEQUENCE)
    private long id;

    @OneToMany(mappedBy = "parent", casade = CasadeType.ALL, orphanRemoval = true)
    private Set<C> childList = new HashSet<>();

    public void addChild(C child){

        if(child!=null){
            this.childList.add(child);
            child.setParent(this);
        }
    }

    public void removeChild(C child){

        if(child!=null){
            this.childList.remove(child);
            child.setParent(null);
        }
    }

    public void updateChildren(Collection<C> children){
        childList.forEach(x-> {if(!children.contains(x)) this.removeChild(x); });

        children.forEach(this::addChild);
    }
}

Upvotes: 2

Related Questions