Home > other >  orphans are not getting deleted once changing the parent set JPA 2 Hibernate 5
orphans are not getting deleted once changing the parent set JPA 2 Hibernate 5

Time:09-21

i am probably doing something wrong, but i can not figure out what. i have 2 tables with 2 entities with the following mapping

@Entity
@EntityListeners(AuditingEntityListener.class)
@Table(name = "parent")
public class Parent {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @JsonIgnore
    @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
    @LazyCollection(LazyCollectionOption.FALSE)
    @Getter
    private List<ChildBase> childs;

    public Parent(){

      this.childs = new ArrayList ();

}



@Entity
@Table(name = "childs")
@Getter
@Setter
@ToString
@Accessors(chain = true)
@NoArgsConstructor
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class ChildBase {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    protected long id;

    @JoinColumn(nullable = false)
    @ManyToOne
    @ToString.Exclude
    protected Parent parent;

    public ChildBase(Parent parent){
      this.parent = parent;
      }

}


@Entity
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@Getter
@Setter
@Accessors(chain = true)
public class MyChild extends ChildBase {
    @Enumerated(EnumType.STRING)
    @Column(name = "name")
    private String name;

    public MyChild(String name, Parent parent) {
        super(parent);
        this.name = name;
    }

the problem appears once i try to disconnect a parent from a child with the following test:

@Test
public void test(){

Parent parent = new Parent();
MyChild child1 = new MyChild("a", parent);
MyChild child2 = new MyChild("a", parent);
parent.getChilds.add(child1);
parentRepository.save(parent);

parent.getChilds.remove(child1);
parent.getChilds.add(child2);
parentRepository.save(parent);
}

i am expecting to see only the second child row in "childs" table, but i see them both.

Edit:

i have tried as well to reference null from child before second save like this: child1.setParent(null). it does not help either

CodePudding user response:

This is a bidirectional relation and MyChild respectively ChildBase is your owning side of the relation.

To trigger the orphan-removal you have to child1.setParent(null), too.

UPDATE: did a setup provided from chat. here are the classes and it is working totally fine.

@Entity
@EntityListeners(AuditingEntityListener.class)
@Table(name = "parent")
public class Parent {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @JsonIgnore
    @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
    @LazyCollection(LazyCollectionOption.FALSE)
    @Getter
    private List<ChildBase> childs;

    public Parent(){

      this.childs = new ArrayList<>();
    }

}
@Entity
@Table(name = "childs")
@Getter
@Setter
@ToString
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@Accessors(chain = true)
@NoArgsConstructor
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class ChildBase {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @EqualsAndHashCode.Include
    protected long id;

    @JoinColumn(nullable = false)
    @ManyToOne
    @ToString.Exclude
    protected Parent parent;

    public ChildBase(Parent parent){
      this.parent = parent;
    }

}
@Entity
@NoArgsConstructor
@Getter
@Setter
@Accessors(chain = true)
public class MyChild extends ChildBase {
  
    @Column(name = "name")
    private String name;

    public MyChild(String name, Parent parent) {
        super(parent);
        this.name = name;
    }
}

And here is the test. After executing there is only childB in the database.

    @Test
    void test() {
        Parent parent = new Parent();
        MyChild child1 = new MyChild("childA", parent);
        MyChild child2 = new MyChild("childB", parent);
        parent.getChilds().add(child1);
        parentRepository.save(parent);

        parent.getChilds().remove(child1); // first remove
        child1.setParent(null);            // set parent null

        parent.getChilds().add(child2);
        parentRepository.save(parent);
    }
  • Related