频 道 直 达 - 新闻 - 读书 - 培训 - 教程 - 前沿 - 组网 - 系统应用 - 安全 - 编程 - 存储 - 操作系统 - 数据库 - 服务器 - 专题 - 产品 - 案例库 - 技术圈 - 博客 - BBS
51CTO.COM_中国领先的IT技术网站
找资料:

使用hibernate实现树形结构无限级分类

作者: 出处:JavaEye  (  ) 砖  (  ) 好  评论 ( ) 条  进入论坛
更新时间:2006-11-22 13:21
关 键 词:Java  hibernate  树形  分类
阅读提示:在系统中,经常会用到无限级的树形结构分类,如组织机构管理、商品/地区分类等等。本文介绍了使用hibernate实现一套树形结构的处理方法。

在系统中,经常会用到无限级的树形结构分类,如组织机构管理、商品/地区分类等等。一般无外采用两种方式:

一是类似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;   
}       
}  

(责任编辑 火凤凰 sunsj@51cto.com  TEL:(010)68476636-8007)


发表
查看
我也说两句

匿名发表

(如果看不清请点击图片进行更换)


中 国 领 先 的 IT 技 术 网 站 ·
技 术 成 就 梦 想
·Java基础教程 (查看52371次)
·UML类图详解 (查看46839次)
·Java编程开发手册 (查看25118次)
·UML统一建模语言 (查看24099次)
·C#技术开发指南 (查看22406次)
·Java编程开发手册 (1195个砖)
·Java基础教程 (429个砖)
·C#技术开发指南 (304个砖)
·PB开发教程 (220个砖)
·.NET开发手册 (217个砖)
·Java编程开发手册 (653个好)
·Java基础教程 (569个好)
·.NET开发手册 (251个好)
·PB开发教程 (209个好)
·Delphi开发技术手册 (174个好)
订阅技术快讯
电子杂志下载
名称:网络安全精品应用黄皮书
简介:《2007精品网络安全黄皮书》包括了9个大类24个小类, 800余篇文章,内容包含了熊猫烧香病毒、DDOS攻击、ARP病等热点问题的介绍及解决方案。从病毒查杀、防范、系统、数据等各方面的安全设置到黑客技术的了解、防范,涉及到了安全应用的全部领域, 由浅至深内容全面。
名称:Vista精品应用黄皮书
简介:《Vista精品应用黄皮书》囊括了Vista的各方面内容。此次的精简版,是将里面的内容做了提取,便于用户下载和使用。内容包含了各种Vista的安装与实施、技巧与解析以及各种Vista相关学习文档和相关软件的安全下载。该电子书是了解和应用Vista人员必备的工具手册,并且也是第一本
名称:2006中国IT论坛精品集合
简介:本书由“51CTO论坛推广联盟”制作完成。书中所有内容均来自各联盟成员的论坛(网站)。制作本书的目的是为了集中大家的优势资源,将更多更精彩的内容带给广大技术爱好者。本书是联盟成立以来制作的第一本书。
关键字阅读
频道精选
主编信箱 热线:010-66476606 告诉我们您想看的:专题 文章
关于我们 | 诚聘英才 | 联系我们 | 网站大事 | 意见反馈 | 网站地图
Copyright©2005-2007 51CTO.COM 版权所有