简体   繁体   中英

JPA/Hibernate fails to save moved child

We have a tree of objects called Category where each category has zero or more child categories. Specifically:

@Entity
@Table(name = "category", schema = "customer")
public class Category extends AccountOwned implements OrdinalOwner {

    @ManyToOne
    @JoinColumn(name = "parent_category_id")
    private Category parent;

    @Column(name = "name")
    private String name;

    @Column(name = "ordinal")
    private int ordinal;

    @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    @OrderBy("ordinal")
    private List<Category> children;

    ... getters/setters

}

We permit child categories to be moved around (their ordinal is changed) AND we permit them to move between parents.

I'm not using any explicit saves. The updates are wrapped in a Spring @Transactional.

If I have a tree like this:

Top Category
    Item 1
        Child 1a
        Child 1b
    Item 2
        Child 2a
    Item 3
        Child 3a
        Child 3b
        Child 3c

I can move Item 3 under Item 1 as a child and it works. The tree is saved properly.

I can move Child 1b under Item 2 as a child and it also works. The tree is saved correctly.

However, if I move anything up the tree, the save doesn't work. For example, if move Child 1b under Top Category, Item 1-3 remain good, but Child 1b is gone forever.

As I move Child 1b to Top Category (by adding it to Top Category's children), I can see it getting removed from Item 1's children - which is good. I can see it correctly getting added to Top Category's children. And I can confirm that the parents of all categories are getting set correctly during the move.

It seems to me that JPA/Hibernate is detecting the removal of the child from one collection and performing a delete on the object, so when it reaches the add to the other list, the object is gone already.

This looks like a bug to me in Hibernate. Can anyone help. If it's a limitation of JPA/Hibernate, how can the logic be achieved?


EDIT: Hmmm, I can see several other people reporting this issue but not find any real solution. I'm using hibernate 5.1.1.

I had to create a work around for this equivalent to:

  1. Remove the orphanRemoval=true
  2. Because we use a central framework for managing the transformation of RESTful collections to JPA collections, I added something to that framework to track children being relocated within the tree as well as tracking deletes. If a child is found to relocate, it leaves it alone. Any truely deleted children, it explicitly deletes them using the CategoryRepository.delete() method.

Unfortunately I can't share the code here because the framework is proprietary.

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