1

I am using Spring Data REST and I have the following entities in my domain.

Atoll.class

@Entity
@Data
public class Atoll {

    @Id
    @GeneratedValue
    private Long id;

    private String atollName;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "atoll_id")
    private List<Island> islands = new ArrayList<>();

}

Island.class

@Entity
@Getter
@Setter
public class Island extends Auditable{

    @Id
    @GeneratedValue
    private Long id;

    private String islandName;

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Island that = (Island) o;
        return Objects.equals(this.getCreatedDate(), that.getCreatedDate());

    }

    @Override
    public int hashCode() {
        return Objects.hash(this.getCreatedDate());
    }

}

Now I can persist both Atoll and Islands by sending a POST to /atolls endpoint with the following JSON.

{
    "atollName":"Haa Alif",
    "islands":[{
        "islandName":"Dhidhdhoo"
    }]
}

But when I send a PATCH to atolls/1 with an empty array of islands to remove all the islands in the atoll it gives me the following exception

A collection with cascade=\"all-delete-orphan\" was no longer referenced by the owning entity instance: com.boot.demo.model.Atoll.islands; nested exception is org.hibernate.HibernateException: A collection with cascade=\"all-delete-orphan\" was no longer referenced by the owning entity instance: com.boot.demo.model.Atoll.island

I searched stackoverflow and found this answer where it says this mainly occurs due to equals and hashCode method so I override the default equals and hashCode method but the error is still the same(the createdDate used in equals method is part of Auditable class).

So what causes this exception and how do I fix this?

Charlie
  • 3,113
  • 3
  • 38
  • 60
  • Have you managed to solve the issue? – lzagkaretos Jan 17 '18 at 19:46
  • the method in the ans did not work – Charlie Jan 21 '18 at 15:19
  • Why do you use createdDate for hashcode and equals? Why not the ID? Can you try to change that and see if you get the same results? Or maybe use both. I wonder if it might be that two such objects have the same createdDate, which can create a conflict. – Stef Jan 23 '18 at 15:19
  • You could also try this http://cristian.sulea.net/blog.php?p=2014-06-28-hibernate-exception-a-collection-with-cascade-all-delete-orphan-was-no-longer-referenced-by-the-owning-entity-instance – Stef Jan 23 '18 at 15:24

1 Answers1

0

You have to implements add/remove methods in the Atoll class.

So, your mapping :

@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "atoll_id")
private List<Island> islands = new ArrayList<>();

And the two add/remove methods:

public void addIsland(Island island) {
    this.getIslands().add(island);
}

public void removeIsland (Island island) {
    this.getIslands().remove(island);
}
gantoin
  • 158
  • 1
  • 8
  • does spring data REST handle these methods automatically if I add them? – Charlie Jan 17 '18 at 14:08
  • I think so, yes. The parent entity, features this two methods which are used to synchronize of the @OneToMany association. Take a look at this article : https://vladmihalcea.com/a-beginners-guide-to-jpa-and-hibernate-cascade-types/ – gantoin Jan 17 '18 at 14:34
  • I haven't tried it yet. but I will let you know if I could get it working – Charlie Jan 18 '18 at 14:05