
推薦:更多Hiernate開發資料
在系統中,經常會用到無限級的樹形結構分類,如組織機構管理、商品/地區分類等等。一般無外采用兩種方式:
一是類似struts-menu(http://struts-menu.sourceforge.net)的XML文件管理方式,配置起來比較方便,但很難與系統中其它應用數據集成;
二是使用數據庫存儲,定義父子關系。
在我們現在開發的一個產品中,使用hibernate實現了一套樹形結構的處理方法,簡介如下:
■演示地址:http://219.143.69.2:8000/treetest/menumanage.do?todoaction=list
演示的是系統菜單的層次實現。由于菜單本身屬于權限系統的一部分,存儲在數據庫中后可以方便的與部門、用戶、崗位、職務等進行關聯,并進行權限控制。
■樹形結構顯示,使用的是xtree。為便于編輯維護,自己寫了一個左鍵彈出菜單(xtree的右鍵事件無法更改),進行節點的添加、修改、刪除、轉移操作。(PS:這套維護界面是完全跨瀏覽器的,有興趣的不妨一試)
■關聯關系:
可以使用objects對象來配置關聯關系,實現多對多/一對多等關系。在BaseTree中,getObjects()方法是abstract的,可以根據需要自己定義。如論壇分類與每個分類所對應的貼子相關聯,商品分類與商品編碼相關聯等,可以根據需要來處理hbm文件。若需要多項關聯,亦可擴展。如菜單與用戶、部門、崗位分別進行關聯
■hibernate2.1.7的一個bug,在這個測試源碼的dao中,TreeManager的getRoots方法,
session.createQuery(" from " + cls.getName() + " where enabled=? and parent_id is null order by id");
在hibernate2中必須像寫成parent_id is null,才能正確運行,這應該是2.1.7中的一個bug。而hibernate3中,可以使用parent is null的hsql。
■主要代碼:
繼承關系如下,假如要實現國家分類:
CountryTree extends BaseTree(abstract class)
BaseTree(abstract class) implements Tree(interface)
為節省版面,下面代碼去掉了javadoc
Tree.java 代碼
- /**
- * 實現了樹的基本操作,上溯、下溯、子節點的添加/移除和遞歸查找、對象關聯等
- */
- package test.testtree.base;
- import java.util.Set;
- public interface Tree {
- public String getCode();
- public String getName();
- public String getDescription();
- public Tree getParent();
- public boolean isRoot();
- public boolean isLeaf();
- public boolean isParentOf(Tree tree);
- public boolean isChildOf(Tree tree);
- public void addChild(Tree tree);
- public void rmChild(Tree tree);
- public Set getAllChildren();
- public Set getChildren();
- public Set getAllLeaves();
- public void addObject(Object obj);
- public void rmObject(Object obj);
- public Set getObjects();
- public Long getId();
- }
BaseTree.java代碼
- package test.testtree.base;
- import java.util.*;
- public abstract class BaseTree extends BasePojo implements Tree{
- protected String code;
- protected String name;
- protected String description;
- protected BaseTree parent;
- protected Set children = new HashSet();
- protected Set objects = new HashSet();
- public void setCode(String code) {
- this.code = code;
- }
- abstract public String getCode();
- public void setName(String name) {
- this.name = name;
- }
- abstract public String getName();
- public void setDescription(String description) {
- this.description = description;
- }
- abstract public String getDescription();
- abstract public Tree getParent();
- public boolean isRoot() {
- return (getParent()==null);
- }
- public boolean isLeaf() {
- return (this.getChildren().size()==0);
- }
- public boolean isParentOf(Tree tree) {
- if (tree==null || ((BaseTree) tree).equals(this)) {
- /*如果對方為空*/
- return false;
- }else if(this.isLeaf()){
- /*如果自己為葉子,則返回FALSE*/
- return false;
- }else if(tree.isRoot()){
- /*如果對方為根,返回FALSE*/
- return false;
- }else{
- BaseTree bt = (BaseTree) (tree.getParent());
- if (this.equals(bt)){
- /*如果對方的父節點是自己,則返回TRUE*/
- return true;
- }else{
- /*判斷對方的父節點是否是自己的孩子,進行遞歸*/
- return isParentOf(bt);
- }
- }
- }
- public boolean isChildOf(Tree tree) {
- return (tree.isParentOf(this));
- }
- public void addChild(Tree tree) {
- children.add(tree);
- }
- public void rmChild(Tree tree) {
- children.remove(tree);
- ((BaseTree) tree).setParent(null);
- }
- public Set getAllLeaves() {
- Set set_old = this.getAllChildren();
- Set set = new HashSet();
- set.addAll(set_old);
- Iterator itr = set_old.iterator();
- while(itr.hasNext()){
- BaseTree bt = (BaseTree) itr.next();
- if (! bt.isLeaf()){
- set.remove(bt);
- }
- }
- return set;
- }
- public Set getAllChildren() {
- Set set = new HashSet();
- Stack stack = new Stack();
- stack.push(this);
- while(!stack.empty()){
- BaseTree bt = (BaseTree) stack.pop();
- set.add(bt);
- Iterator itr = bt.getChildren().iterator();
- while(itr.hasNext()){
- BaseTree btchild = (BaseTree) itr.next();
- stack.push(btchild);
- }
- }
- set.remove(this);
- return set;
- }
- public List getMeAndListAllChildren() {
- List lst = new Vector();
- lst.add(this);
- Iterator itr = this.getChildren().iterator();
- while(itr.hasNext()){
- BaseTree bt = (BaseTree) itr.next();
- lst.addAll(bt.getMeAndListAllChildren());
- }
- return lst;
- }
- abstract public Set getChildren();
- public void addObject(Object obj) {
- objects.add(obj);
- }
- public void rmObject(Object obj) {
- objects.remove(obj);
- }
- abstract public Set getObjects();
- public void setParent(Tree parent) {
- this.parent = (BaseTree) parent;
- }
- public void setChildren(Set children) {
- this.children = children;
- }
- public void setObjects(Set objects) {
- this.objects = objects;
- }
- }