同一级别的

时间:2017-08-09 08:55:02

标签: java jpa hierarchical-data

我有一张桌子:

id|name|parent
--------------
1 |test|null
2 |tt1 |1
3 |tt2 |1
4 |tt3 |1
5 |tt4 |2
6 |tt5 |3
7 |tt6 |2

看起来像这棵树:

     test
   /   |   \
  tt1 tt2 tt3
  / \       \
tt4 tt6     tt5

问题是如何在与给定节点相同的级别上查找节点数量。例如:对于tt2,答案为3,对于tt5,答案为3。但我不明白,该怎么做?甚至没有谈到最优化和正确的方式。

我创建了一个java Entity,其对应的映射到表中的同一列,并实现了一个getter,它返回root的路径,以便我可以找到该级别。此外,我已经实现了一个方法,可以找到给定节点的兄弟节点数量。创造了这些吸气剂,因为我认为它会对我有所帮助。

实体:

@Entity(name = "hierarchy")

public class Hierarchy implements Serializable {

    private Integer idNode;
    private String name;
    private Hierarchy parentNode;
    private Set<Hierarchy> children;

    public Hierarchy() {
    }

    public Hierarchy(Integer idNode, String name) {
        this.idNode = idNode;
        this.abbreviation = abbreviation;
    }

    @Id
    @GeneratedValue
    @Column(name = "id")
    public Integer getIdNode() {
        return idNode;
    }

    public void setIdNode(Integer idNode) {
        this.idNode = idNode;
    }

    @Column(name = "name", length = 500)
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @ManyToOne
    @JoinColumn(name = "parent")
    public Hierarchy getParentNode() {
        return parentNode;
    }

    public void setParentNode(Hierarchy parentNode) {
        this.parentNode = parentNode;
    }

    @OneToMany(mappedBy = "parentNode")
    public Set<Hierarchy> getChildren() {
        return children;
    }

    public void setChildren(Set<Hierarchy> children) {
        this.children = children;
    }

    @Override
    public String toString() {
        return "Hierarchy [idNode=" + idNode + ", name=" + name + "]";
    }

    @Transient
    public int getSiblingsNum() {
        if (this.getParentKeyword() == null) {
            return -1;
        }
        return this.getParentNode().getChildren().size() - 1;
    }

    @Transient
    public List<Hierarchy> getPath() {
        Hierarchy name = this;
        List<Hierarchy> path = new ArrayList<>();
        path.add(name);
        while (name.getParentNode() != null) {
            name = name.getParentNode();
            path.add(name);
        }
        return path;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((idNode == null) ? 0 : idNode.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Hierarchy other = (Hierarchy) obj;
        if (idNode == null) {
            if (other.idNode != null)
                return false;
        } else if (!idNode.equals(other.idNode))
            return false;
        return true;
    }
}

1 个答案:

答案 0 :(得分:0)

我建议为这样的问题重新设计数据库模式。您可以查看Bill Karwin章节“天真树”中的SQL Antipatterns一书。

如果这不是一个选项,你必须导航到根目录才能找到元素的级别,然后递归迭代直到找到的级别并计算所有元素。

这样的事情:

public int getSameLevelNum() {
    int level = 0;
    Hierarchy current = this;
    while(current.getParentNode() != null){
        level++;
        current = current.getParentNode();
    }
    return recurse(current, level);
}

int recurse(Hierarchy node, int level){
    if(level == 0) return node.children.size();
    level--;
    int r = 0;
    for(Hierarchy child : node.children)
            r+= recurse(child, level);  

    return r;
}