1:
我们都知道Tree结构是RDBMS的一个死穴。
可是我们常常在实际中碰到这样的结构,比如部门结构,栏目结构....
原来用JDBC来处理这些树结构比较简单,只要解决一个Select抓回一棵树的问题这个关键问题,然后排序一下就搞定了。
在Hibernate中,如何来高效的完成这些工作呢?
以下是一个典型的父子关系的mapping
但是这样的结构,如果要获得某子节点下所有的节点,则要多个SQL(树有几层就调几次)
有更高效的实现办法么?
2:
我做的時候只是先查出第一層,然後對這個根做一個遞歸就可以呀
我们都知道Tree结构是RDBMS的一个死穴。
可是我们常常在实际中碰到这样的结构,比如部门结构,栏目结构....
原来用JDBC来处理这些树结构比较简单,只要解决一个Select抓回一棵树的问题这个关键问题,然后排序一下就搞定了。
在Hibernate中,如何来高效的完成这些工作呢?
以下是一个典型的父子关系的mapping
java代码: |
<class name="test.TreeNode" table="tree"> <id name="id" column="nodeId" type="long" unsaved-value="null"> <generator class="identity"/> </id> <many-to-one name="parent" column="parentId" class="test.TreeNode" cascade="save-update" access="field"/> <property name="xxxx" column="xxxx" type="long" not-null="true"/> </class> |
但是这样的结构,如果要获得某子节点下所有的节点,则要多个SQL(树有几层就调几次)
有更高效的实现办法么?
2:
我做的時候只是先查出第一層,然後對這個根做一個遞歸就可以呀
java代码: |
private void buildChild(FolderListForm folderListForm, DocPO docPO) throws Exception { Collection children = docPO.getChildren(); int order = 1; for (java.util.Iterator it = children.iterator(); it.hasNext();) { DocPO child = (DocPO) it.next(); DocTreeNodeForm docTreeNodeForm = new DocTreeNodeForm(); BeanUtils.copyProperties(docTreeNodeForm, child); folderListForm.getDocTreeNodeFormList().add(docTreeNodeForm); buildChild(folderListForm, child); } } |
3:
请注意parent和children都映射到同一个字段fk_parend_id,对树各种操作居然能成功,不得不佩服Hibernate的强悍!
java代码: |
import java.util.List; import java.util.ArrayList; import java.util.Map; import java.util.Stack; /** * @hibernate.class table="CATS" * dynamic-update="true" * dynamic-insert="true" * */ public class Cat { private Long id; // identifier private List children = new ArrayList(); private Cat parent; /** * @hibernate.id * generator-class="native" * column="cat_id" */ public Long getId() { return id; } private void setId(Long id) { this.id = id; } public Cat addChildren(Cat child) { children.add(child); return this; } /** * @hibernate.list * cascade="all" * lazy="true" * @hibernate.collection-key * column="fk_parent_id" * @hibernate.collection-one-to-many * class="com.nosqldb.bo.Cat" * @hibernate.collection-index * column="index_parent_id" */ public List getChildren() { return children; } /** * @param children The children to set. */ public void setChildren(List children) { this.children = children; } /** * @return * @hibernate.many-to-one * column="fk_parent_id" * class="com.nosqldb.bo.Cat" * cascade="all" */ public Cat getParent() { return parent; } /** * @param parent The parent to set. */ public void setParent(Cat parent) { this.parent = parent; } /** * 树形遍历 * 不用递归,用堆栈. * 这里只是做为例子,本人不建议把业务逻辑封装在Entity层. */ public List getVisitResults() { List l = new ArrayList(); Stack s = new Stack(); s.push(this); while (s.empty() == false) { Cat c = (Cat) s.pop(); l.add(c); List children = c.getChildren(); if (children != null) { for (int i = 0; i < hildren.size(); i++) { Cat cat = (Cat) children.get(i); s.push(cat); }//end for }//end if }//end while return l; } } |