Best practice for setter in a bidirectional self-referencing relationship
15:39 20 Aug 2026

I have a JPA entity with a self-referencing relationship where all children of the same family point upward to the same root parent. It currently looks like this:

public class Item {
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parentId")
    private Item parent;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "parent")
    private List children = new ArrayList<>();

    public Item setParent(Item parent) {
        this.parent = parent;
        return this;
    }
    
    public void addChild(Item child) {
        Item root = this.getRootItem();
        child.setParent(root);
        root.children.add(child);
    }
    
    public Item getRootItem() {
        return Objects.requireNonNullElse(this.getParent(), this);
    }
}

I'm not sure how much responsibility should I put in the setter, add, and getter method. Should I only handle the logic inside addChild, or do I need to do it in all of them? Is there a best practice on how to handle them for this specific case?

best-practices java oop jpa design-patterns