OpenJPA 1.2.x 使用 JPQL 选择树结构
我正在使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
那么您的数据很可能是错误的。仔细检查根是否没有父级。
Then your data are very likely wrong. Double check that the root has no parent.
我认为你所做的事情是正确的并且应该有效。您将完整的树结构加载到持久性上下文中,然后获取对根节点的引用。也许你的树遍历有问题?这将是唯一可能导致 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?请查看我的数据库结构:
这就是 JPA 不起作用的原因:(
请参阅第一行。它是树的根。似乎 JPA 将其读取为引用自身的子级(PARENT_ID 确实存在于表中,因此 JOIN 可以是执行)。
我已经更改了数据库值:
现在可以了!
Please see my DB struccture:
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:
Now it works! Yeah! :)