简体   繁体   中英

Spring Data Repository does not delete Entity when using @OneToMany Annotations

Code sample with unit tests to explain this question can be found here:

Scenario:

  • SpringBoot Application with Spring Boot Starter Data JPA integration
  • Relational Database using H2 In Memory Database

Database Entities:

  • Entity1 with @OneToMany Relationship to Entity2
  • Entity2 with @ManyToOne Relationship to Entity1

The entities:

@Entity
@Table(name="entity_1")
public class Entity1 {
    @Id
    @Column(name="id", columnDefinition="char(36)")
    private String id;

    @OneToMany(
            mappedBy="entity1",
            cascade = CascadeType.ALL,
            orphanRemoval = true
    )
    private List<Entity2> entity2 = new ArrayList<>();

    public String getId() {
        return id;
    }

    public Entity1 setId(String id) {
        this.id = id;
        return this;
    }

    public List<Entity2> getEntity2() {
        return entity2;
    }

    public Entity1 setEntity2(List<Entity2> entity2) {
        this.entity2 = entity2;
        return this;
    }
}
@Entity
@Table(name="entity_2")
public class Entity2 {
    @Id
    @Column(columnDefinition = "char(36)")
    private String id;

    @ManyToOne(optional = false)
    @JoinColumn(name="entity1", referencedColumnName = "id")
    private Entity1 entity1;

    public String getId() {
        return id;
    }

    public Entity2 setId(String id) {
        this.id = id;
        return this;
    }

    public Entity1 getEntity1() {
        return entity1;
    }

    public Entity2 setEntity1(Entity1 entity1) {
        this.entity1 = entity1;
        return this;
    }
}

Entity relationship:

Entity1 e1 = new Entity1().setId("1_1");
Entity2 e2_1 = new Entity2().setId("2_1");
Entity2 e2_2 = new Entity2().setId("2_2");

e1.getEntity2().add(e2_1);
e1.getEntity2().add(e2_2);

e2_1.setEntity1(e1);
e2_2.setEntity1(e1);

entity1Repo.save(e1);

Question: When I try to delete an Entity2 from the database using the Spring Data Repository assigned to Entity2 , it does not work. However, I don't get any error either.

Example:

public void deleteEntity2UsingRepo2() {
    Entity1 e1 = entity1Repo.findAll().get(0);
    Entity2 e2 = e1.getEntity2().get(0);

    entity2Repo.delete(e2);
}

Some logging entries:

2022-08-24 13:35:26.577 TRACE 4956 --- [           main] o.h.e.i.DefaultDeleteEventListener       : Deleting a persistent instance
2022-08-24 13:35:26.578 TRACE 4956 --- [           main] o.h.e.i.DefaultDeleteEventListener       : Deleting [de.peravs.database.sample.entity.Entity2#2_1                                 ]
2022-08-24 13:35:26.579 DEBUG 4956 --- [           main] o.h.e.t.internal.TransactionImpl         : committing

and

2022-08-24 13:35:26.581 DEBUG 4956 --- [           main] o.hibernate.internal.util.EntityPrinter  : Listing entities:
2022-08-24 13:35:26.581 DEBUG 4956 --- [           main] o.hibernate.internal.util.EntityPrinter  : de.peravs.database.sample.entity.Entity2{entity1=de.peravs.database.sample.entity.Entity1#1_1                                 , id=2_2                                 }
2022-08-24 13:35:26.581 DEBUG 4956 --- [           main] o.hibernate.internal.util.EntityPrinter  : de.peravs.database.sample.entity.Entity2{entity1=de.peravs.database.sample.entity.Entity1#1_1                                 , id=2_1                                 }
2022-08-24 13:35:26.581 DEBUG 4956 --- [           main] o.hibernate.internal.util.EntityPrinter  : de.peravs.database.sample.entity.Entity1{entity2=[de.peravs.database.sample.entity.Entity2#2_1                                 , de.peravs.database.sample.entity.Entity2#2_2                                 ], id=1_1                                 }

Why is Entity2 not being deleted using this way?

My Repositories:

public interface Entity1Repo extends Repository<Entity1, String> {
    List<Entity1> findAll();
    void save(Entity1 entity1);
}

public interface Entity2Repo extends Repository<Entity2, String> {
    void delete(Entity2 entity2);
}

Example2 (works as expected):

public void deleteEntity2UsingRepo1() {

    Entity1 e1 = entity1Repo.findAll().get(0);
    e1.getEntity2().remove(0);
    entity1Repo.save(e1);
}

In your case Entity1 is the parent and Entity2 is a child. The remove entity transition should cascade from parent to children, not the other way around. So if you have many parents for the same entity you should iterate threw all of them and do the same operation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM