OpenJPA 1.2.x 使用 JPQL 选择树结构

发布于 2024-09-30 16:42:38 字数 3916 浏览 1 评论 0原文

我正在使用 OpenJPA 1.2.x (JPA1)。问题是我无法继续使用 JPQL 查询树结构。

请查看我的实体:

@NamedQueries(
         { 
           @NamedQuery(
             name="Department.getFullTree",
             query="SELECT dep FROM Department dep LEFT JOIN fetch dep.children"
           )
         }
        )
@Entity
public class Department {

    public static final Long ROOT_ID = 0L;

    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="DEPARTMENT_SEQ")
    @SequenceGenerator(name="DEPARTMENT_SEQ", sequenceName="DEPARTMENT_SEQ", allocationSize=1)
    @Column(name="ID")
    private Long id;

    @Column(name="PARENT_ID")
    private Long parentId;

    @ManyToOne(targetEntity = Department.class, fetch = FetchType.EAGER)
    @JoinColumn(name = "PARENT_ID")
    private Department parent;

    @Column(name="LABEL")
    private String label;

    @OneToMany(mappedBy = "parent", 
               targetEntity = Department.class, 
               fetch=FetchType.LAZY, 
               cascade = {CascadeType.PERSIST, CascadeType.ALL})
    private List<Department> children;

和我的无状态 bean 方法:

public Department getFullTree(){
    em.createNamedQuery("Department.getFullTree").getResultList();
    Department root = em.find(Department.class, Department.ROOT_ID); 
    return root;
}

我的目标是从根开始获得完整的部门树。 我尝试过这种方法:

这是真的吗?我正在使用 DB2。并且将来还会用到。 用于获取整个树的 JPA 查询

这似乎不起作用: http://www.tikalk.com/java/ load-a-tree-with-jpa-and-hibernate

我尝试重复,但在遍历树时出现 stackoverflow 错误(根本没有超过 200 个节点)。 调试输出显示 root 将其自身作为子级,因此它是圆形链接结构...

接下来我必须尝试什么?

更新: 这是我的遍历代码:

public class TreeTagHelper {

    private static final Logger LOG = LoggerFactory.getLogger(TreeTagHelper.class);

    private Department root;
    private JspWriter out;

    public TreeTagHelper(Department root, JspWriter out){
        LOG.trace("#init");
        this.root = root;
        this.out = out;
    }

    public void printTree() throws Exception{
        LOG.trace("#printTree -> start");
        out.println("<ul id=\"tree-root\"> ");      
        for(Department dep : root.getChildren()){
            printNode(dep, out);
        }       
        closeUL(out);
        LOG.trace("#printTree -> end");
    }

    public static void printNode(Department dep, JspWriter out) throws Exception{
        LOG.trace("#printNode title[{}] children.size()[{}]",dep.getLabel(), (dep.getChildren() == null ? "NULL" : dep.getChildren().size()) );
        openLI(out);
        out.print("<span id=\"tree_node_"+dep.getId()+"\" class=\"ekp-tree-node\" onclick=\"ekpCommon.tree.toggleBullet(this)\">"+dep.getLabel()+"</span>");
        if(dep.getChildren()!=null){
            openUL(out);
            for(Department child : dep.getChildren()){
                printNode(child, out);
            }
            closeUL(out);
        }

        closeLI(out);
    }

    public static void openUL(JspWriter  out) throws Exception{
        out.println("<ul>");
    }

    public static void closeUL(JspWriter out) throws Exception{
        out.println("</ul>");       
    }

    public static void openLI(JspWriter out) throws Exception{
        out.println("<li>");
    }

    public static void closeLI(JspWriter out) throws Exception{
        out.println("</li>");       
    }

LOG.trace("#printNode title[{}]children.size()[{}]",dep.getLabel(), (dep.getChildren() == null ? " NULL" : dep.getChildren().size()) );

始终输出:“#printNode title[所有部门]children.size()[19]” 似乎根(“所有部门”)有 19 个子项。确实如此,我在数据库中检查过。 但每个孩子都是根! 所以它是无限结构......??? Root没有孩子吗?它自己取东西吗?

I'm using OpenJPA 1.2.x (JPA1). The problem is that I can't get on with querying tree structure using JPQL.

Please, see my entity:

@NamedQueries(
         { 
           @NamedQuery(
             name="Department.getFullTree",
             query="SELECT dep FROM Department dep LEFT JOIN fetch dep.children"
           )
         }
        )
@Entity
public class Department {

    public static final Long ROOT_ID = 0L;

    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="DEPARTMENT_SEQ")
    @SequenceGenerator(name="DEPARTMENT_SEQ", sequenceName="DEPARTMENT_SEQ", allocationSize=1)
    @Column(name="ID")
    private Long id;

    @Column(name="PARENT_ID")
    private Long parentId;

    @ManyToOne(targetEntity = Department.class, fetch = FetchType.EAGER)
    @JoinColumn(name = "PARENT_ID")
    private Department parent;

    @Column(name="LABEL")
    private String label;

    @OneToMany(mappedBy = "parent", 
               targetEntity = Department.class, 
               fetch=FetchType.LAZY, 
               cascade = {CascadeType.PERSIST, CascadeType.ALL})
    private List<Department> children;

And my stateless bean method:

public Department getFullTree(){
    em.createNamedQuery("Department.getFullTree").getResultList();
    Department root = em.find(Department.class, Department.ROOT_ID); 
    return root;
}

My aim is to get full department tree starting from root.
I've tried this approach:

Is that true? I'm using DB2. And will use it in future.
JPA query for getting the whole tree

This seems like doesn't work:
http://www.tikalk.com/java/load-a-tree-with-jpa-and-hibernate

I've tried to repeat, but I get stackoverflow error while traversing tree (don't have more than 200 nodes at all).
Debug output showed that root has itself as a child, so it's round-linked structure...

What do I have to try next?

UPD:
Here is my traverse code:

public class TreeTagHelper {

    private static final Logger LOG = LoggerFactory.getLogger(TreeTagHelper.class);

    private Department root;
    private JspWriter out;

    public TreeTagHelper(Department root, JspWriter out){
        LOG.trace("#init");
        this.root = root;
        this.out = out;
    }

    public void printTree() throws Exception{
        LOG.trace("#printTree -> start");
        out.println("<ul id=\"tree-root\"> ");      
        for(Department dep : root.getChildren()){
            printNode(dep, out);
        }       
        closeUL(out);
        LOG.trace("#printTree -> end");
    }

    public static void printNode(Department dep, JspWriter out) throws Exception{
        LOG.trace("#printNode title[{}] children.size()[{}]",dep.getLabel(), (dep.getChildren() == null ? "NULL" : dep.getChildren().size()) );
        openLI(out);
        out.print("<span id=\"tree_node_"+dep.getId()+"\" class=\"ekp-tree-node\" onclick=\"ekpCommon.tree.toggleBullet(this)\">"+dep.getLabel()+"</span>");
        if(dep.getChildren()!=null){
            openUL(out);
            for(Department child : dep.getChildren()){
                printNode(child, out);
            }
            closeUL(out);
        }

        closeLI(out);
    }

    public static void openUL(JspWriter  out) throws Exception{
        out.println("<ul>");
    }

    public static void closeUL(JspWriter out) throws Exception{
        out.println("</ul>");       
    }

    public static void openLI(JspWriter out) throws Exception{
        out.println("<li>");
    }

    public static void closeLI(JspWriter out) throws Exception{
        out.println("</li>");       
    }

LOG.trace("#printNode title[{}] children.size()[{}]",dep.getLabel(), (dep.getChildren() == null ? "NULL" : dep.getChildren().size()) );

always outputs: "#printNode title[All departments] children.size()[19]"
Seems like the root("All departments") has 19 children. It's true, I checked it in my DB.
But each children is the root!
So it's infinite structure...??? Root doesn't get children? It fetches itself?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

清醇 2024-10-07 16:42:38

我尝试重复,但在遍历树时出现 stackoverflow 错误(根本没有超过 200 个节点)。调试输出显示 root 将其自身作为子级,因此它是圆形链接结构...

那么您的数据很可能是错误的。仔细检查根是否没有父级。

I've tried to repeat, but I get stackoverflow error while traversing tree (don't have more than 200 nodes at all). Debug output showed that root has itself as a child, so it's round-linked structure...

Then your data are very likely wrong. Double check that the root has no parent.

回忆凄美了谁 2024-10-07 16:42:38

我认为你所做的事情是正确的并且应该有效。您将完整的树结构加载到持久性上下文中,然后获取对根节点的引用。也许你的树遍历有问题?这将是唯一可能导致 StackOverflowError 的事情。你能发布你的代码吗?

I think what you are doing is correct and should work. You are loading the complete tree structure into the persistence context and then obtain a reference to the root node. Perhaps there is something wrong with your tree traversing? This would be the only thing that could cause a StackOverflowError. Could you post your code?

堇色安年 2024-10-07 16:42:38

请查看我的数据库结构:

ID    PARENT_ID    LABEL
0     0        All Departments
1000   0           Central office

这就是 JPA 不起作用的原因:(

请参阅第一行。它是树的根。似乎 JPA 将其读取为引用自身的子级(PARENT_ID 确实存在于表中,因此 JOIN 可以是执行)。

我已经更改了数据库值:

ID    PARENT_ID    LABEL
0     -1           All Departments
1000   0           Central office

现在可以了!

Please see my DB struccture:

ID    PARENT_ID    LABEL
0     0        All Departments
1000   0           Central office

That is why JPA didn't work :(

See the first row. It's the root of the tree. Seems like JPA read it as a child referencing to itself (PARENT_ID does exist in table, so JOIN can be performed).

I've change DB values:

ID    PARENT_ID    LABEL
0     -1           All Departments
1000   0           Central office

Now it works! Yeah! :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文