Java 从家长JPA获取所有子代和子代

Java 从家长JPA获取所有子代和子代,java,mysql,hibernate,jpa,Java,Mysql,Hibernate,Jpa,我有一张桌子,可以有相同类型的父母。 在Java中,子对象可以到达父对象,但父对象没有子对象列表 在MySQL中,我能够创建以下查询,该查询为我提供父级的子级和子级,但我无法将其转换为JPA Java 如何翻译此查询: 选择* 从表中选择T1 内连接 从TABLE.parentId=966的表中选择id作为T2 在T2.id=T1.parentId或T1.parentId=966上 按T1.id分组 在java语言中,使用Criteria builder和Criteria Query,我已经尝试

我有一张桌子,可以有相同类型的父母。 在Java中,子对象可以到达父对象,但父对象没有子对象列表

在MySQL中,我能够创建以下查询,该查询为我提供父级的子级和子级,但我无法将其转换为JPA Java

如何翻译此查询:

选择* 从表中选择T1 内连接 从TABLE.parentId=966的表中选择id作为T2 在T2.id=T1.parentId或T1.parentId=966上 按T1.id分组 在java语言中,使用Criteria builder和Criteria Query,我已经尝试了以下方法:

CriteriaBuilder cb=em.getCriteriaBuilder; CriteriaQuery cq=cb.createQueryTABLE.class; 根表=cq.fromTABLE.class; 谓词结果=cb.连词; Join TABLEJoin=tABLE.joinparent,JoinType.INNER; 结果=cb.andresult,cb.equalgenericLocationJoin.getparent,位置; em.createQuerycq.selecttAble.whereresult.getResultList; 但这只给了我直接的孩子,没有给我亚孩子

谢谢你的帮助

实体:

@Entity
@Table(name = "table")
public final class TABLE {

    @Column(nullable = false, unique = true, length = 20)
    private String externalId;

    @Column(nullable = false, length = 50)
    private String name;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "parentId", nullable = true)
    private TABLE parent;
}
@Entity
@Table(name = "some_entity")
public final class SomeEntity {

    @Column(nullable = false, unique = true, length = 20)
    private String externalId;

    @Column(nullable = false, length = 50)
    private String name;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "parentId", nullable = true)
    private SomeEntity parent;

    @OneToMany(mappedBy = "parent")
    private List<SomeEntity> children; //or Set<>

    //returns direct children
    public List<SomeEntity> getChildren(){
        return children;
    } 

    //returns all children to any level
    public List<SomeEntity> getAllChildren(){
        getAllChildren(this);
    }

    //recursive function to walk the tree
    private List<SomeEntity> getAllChildren(SomeEntity parent){
        List<SomeEntity> allChidren = new ArrayList<>();

        for(SomeEntity child : children){
            allChildren.add(child);
            allChildren.addAll(getAllChildren(child);
        }

        return allChildren;
    }
}

您可以在域模型中通过使关系双向并编写递归方法遍历树来处理此问题。这样做的一个优点是,它可以处理任何级别的儿童

这将类似于下面的内容,然后对于任何情况,您都可以执行以下操作:

SomeEntity e = //;
e.getChildren(); //only direct children
e.getAllChildren(); //all children
实体:

@Entity
@Table(name = "table")
public final class TABLE {

    @Column(nullable = false, unique = true, length = 20)
    private String externalId;

    @Column(nullable = false, length = 50)
    private String name;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "parentId", nullable = true)
    private TABLE parent;
}
@Entity
@Table(name = "some_entity")
public final class SomeEntity {

    @Column(nullable = false, unique = true, length = 20)
    private String externalId;

    @Column(nullable = false, length = 50)
    private String name;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "parentId", nullable = true)
    private SomeEntity parent;

    @OneToMany(mappedBy = "parent")
    private List<SomeEntity> children; //or Set<>

    //returns direct children
    public List<SomeEntity> getChildren(){
        return children;
    } 

    //returns all children to any level
    public List<SomeEntity> getAllChildren(){
        getAllChildren(this);
    }

    //recursive function to walk the tree
    private List<SomeEntity> getAllChildren(SomeEntity parent){
        List<SomeEntity> allChidren = new ArrayList<>();

        for(SomeEntity child : children){
            allChildren.add(child);
            allChildren.addAll(getAllChildren(child);
        }

        return allChildren;
    }
}

发布你的实体。非常感谢。我认为这对于这个案例来说是一个足够好的解决方案,问题是我试图在一个查询中完成所有操作。好的,我做了一个轻微的编辑。尚未测试递归部分,但希望在编辑后可以。此解决方案的问题是,它将对数据库产生很大影响,因为对象将始终请求子对象,在必须的情况下,这不是假定要做的。默认情况下是有一个父对象,而不是请求子对象,但在某些情况下需要这种关系。这就是为什么is尝试实现一个可以在需要时使用的查询,而不是在您请求实体的所有时间。子集合是惰性加载的,因此我不确定我是否理解。我看到了一种方法,就是为每个实体添加一个路径,例如,id为1的根父对象将是/并且它的子对象将具有/1/a等等,有了它,您可以进行一个查询,获取每个父项的所有子项。