有没有一种更清晰的方法可以在Spring JPA中构建MappedSuperclass Tree类?

我目前有几个实体作为树,需要将它们保存到数据库。


因此,为了不重复代码,我构建了此类:


@MappedSuperclass

public abstract class TreeStructure<T extends TreeStructure>

{

    @ManyToOne(cascade = CascadeType.PERSIST)

    private T  parent;


    @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)

    protected Set<T> children = new HashSet<>();


    /**

     * Function that is used before deleting this entity. It joins this.children to this.parent and viceversa.

     */

    @Transactional

    @PreRemove

    public void preDelete()

    {

        unregisterInParentsChildren();


        while (!children.isEmpty())

        {

            children.iterator().next().setParent(parent);

        }


    }


    public abstract long getId();


    protected void setParent(T pParent)

    {

        unregisterInParentsChildren();

        parent = pParent;

        registerInParentsChildren();

    }


    /**

     * Register this TreeStructure in the child list of its parent if it's not null.

     */

    private void registerInParentsChildren()

    {

        getParent().ifPresent((pParent) -> pParent.children.add(this));

    }


    /**

     * Unregister this TreeStructure in the child list of its parent if it's not null.

     */

    private void unregisterInParentsChildren()

    {

        getParent().ifPresent((pParent) -> pParent.children.remove(this));

    }


    /**

     * Move this TreeStructure to an new parent TreeStructure.

     *

     * @param pNewParent the new parent

     */

    public void move(final T pNewParent)

    {

        if (pNewParent == null)

        {

            throw new IllegalArgumentException("New Parent required");

        }


        if (!isProperMoveTarget(pNewParent) /* detect circles... */)

        {

            throw new IllegalArgumentException(String.format("Unable to move Object %1$s to new Object Parent %2$s", getId(), pNewParent.getId()));

        }


        setParent(pNewParent);

    }


  

所以,最后要说的是:有没有以更好/更干净的方式实现这一点?这个警告有意义,还是只是Intellij不够聪明?


呼如林
浏览 114回答 2
2回答

慕侠2389804

问题不在于JPA,而在于泛型的使用。首先,更改抽象类签名,使其具有递归类型:public abstract class TreeStructure<T extends TreeStructure<T>>接下来,你不能引用'this',因为你不知道'this'的实现,所以你可以把它强制转换为'T',或者添加一个带有类似签名的抽象方法:public abstract T getImpl();在实现中,只需返回“this”。public T getImpl() {&nbsp; return this;}在侧节点上,访问类中的父类实例变量可能不是一个好主意。向 TreeStructure 类添加一个 addChild 和 removeChild 方法可能是一个更好的主意。

守着一只汪

我有一个非常类似的场景,我没有使用T。相反,我只有抽象类,因为我不需要类型化孩子的灵活性,而且我没有演员表。据我所知(共享代码),它可能会让你接地气,但我不知道你是否有其他要求。在我的情况下,另一个区别是抽象类不是映射的超类,而是.@Inheritance(strategy = InheritanceType.SINGLE_TABLE)如果可以提供帮助,您可以在此存储库中找到完整的工作示例@Inheritance(strategy = InheritanceType.SINGLE_TABLE)public abstract class TreeStructure {&nbsp; &nbsp; ...&nbsp; &nbsp; @ManyToOne(cascade = CascadeType.PERSIST)&nbsp; &nbsp; private TreeStructure&nbsp; parent;&nbsp; &nbsp; @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)&nbsp; &nbsp; protected Set<TreeStructure> children = new HashSet<>();
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java