JPA query for getting the whole tree

前端 未结 2 1648
感情败类
感情败类 2021-01-12 03:01

I have a class which models all categories and they can be ordered hierarchically.

@Entity
@Table(name=\"categories\")
public class Category {
    @Id
    @G         


        
2条回答
  •  醉酒成梦
    2021-01-12 03:47

    First of all, assuming in this hierarchy a "father" can have more than one child, then the father field should be annotated as @ManyToOne.

    If you have a field that all the members of a tree share, or if the tree contains the entire table, then it is possible to do it with JPA in an efficient way, though not through a single JPA query.

    You simply need to prefetch all the members of the tree, and then traverse the tree:

    @Entity
    @Table(name="categories")
    public class Category {
        @Id
        @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="sequence")
        @SequenceGenerator(name="sequence", sequenceName="categories_pk_seq", allocationSize=1)
        @Column(name="id")
        private Long id;
    
        @Column
        private String name;
    
        @ManyToOne
        @JoinColumn(name="idfather")
        private Category father;
    
        @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, 
                   fetch = FetchType.LAZY, 
                   mappedBy = "idfather")
        @OrderBy("name")
        private List subCategories;
    }
    

    Notice the @OrderedBy annotation on the subCategories field.

    Now you can get the entire tree by first loading all the categories into a jumbled list, just so that they'd all be in memory, and then traverse the tree.

    public List getTree() {
        List jumbled = 
            entityManager.createQuery("from Category", Category.class).getResultList();
    
        Category root = null;
        for(Category category : jumbled) {
            if(category.getFather() == null) {
                root = category;
                break;
            }
        }
    
        List ordered = new ArratList();
        ordered.add(root);
        getTreeInner(root, ordered);
    }
    
    private void getTreeInner(Category father, List ordered) {
        for(Category child : father.getSubCategories()) {
            ordered.add(child);
            getTreeInner(child, ordered);
        }
    }
    

    I'm only learning JPA myself right now, so I may be missing something crucial, but this approach seems to work for me.

提交回复
热议问题