论坛首页 Java企业应用论坛

关于在Hibernate中高效的处理Tree结构?

浏览 46839 次
该帖已经被评为精华帖
作者 正文
   发表时间:2004-03-25  
我们都知道Tree结构是RDBMS的一个死穴。
可是我们常常在实际中碰到这样的结构,比如部门结构,栏目结构....
原来用JDBC来处理这些树结构比较简单,只要解决一个Select抓回一棵树的问题这个关键问题,然后排序一下就搞定了。
在Hibernate中,如何来高效的完成这些工作呢?

以下是一个典型的父子关系的mapping
<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(树有几层就调几次)

有更高效的实现办法么?
   发表时间:2004-03-25  
引用
原来用JDBC来处理这些树结构比较简单,只要解决一个Select抓回一棵树的问题这个关键问题,然后排序一下就搞定了。


你如何1条Select就抓回一颗树呢?如果父子关系只有主外键关联来表达,没有其他附加的表征字段的话,除了Oracle的自己的start with ... connect by...之外,我想不出来有什么一条SQL就能抓回整个子树。
0 请登录后投票
   发表时间:2004-03-25  
robbin 写道
引用
原来用JDBC来处理这些树结构比较简单,只要解决一个Select抓回一棵树的问题这个关键问题,然后排序一下就搞定了。


你如何1条Select就抓回一颗树呢?如果父子关系只有主外键关联来表达,没有其他附加的表征字段的话,除了Oracle的自己的start with ... connect by...之外,我想不出来有什么一条SQL就能抓回整个子树。


用空间来换时间
比如为每个node增加一个lft/rgt,然后从上到下编号,这样就可以用一个select抓回所有纪录,某个节点的所有子节点是 "&gt;lft AND &lt;rgt" 的.
  缺点是增加纪录的时候稍微繁琐一些,需要多个SQL,但是大数据量的时候效率很高。
0 请登录后投票
   发表时间:2004-03-25  
那你用Hibernate不也一样吗?增加两个表征层次和位置的属性,到时候,

  where ...    node.lft < AND node.gft > ...
0 请登录后投票
   发表时间:2004-03-26  
acdc:
引用
比如为每个node增加一个lft/rgt,然后从上到下编号,这样就可以用一个select抓回所有纪录,某个节点的所有子节点是 "&gt;lft AND &lt;rgt" 的.


能不能给一例子呢(完成的SQL,和数据进行说明),因为我想了解你这个方法,我觉得可能你这样子有一些情况可能不行(我只是猜想,因为我的智商有限,请原谅).

谢谢了(这样子大家又可以学到也(东西)了)
0 请登录后投票
   发表时间:2004-03-26  
acdc 写道
robbin 写道
引用
原来用JDBC来处理这些树结构比较简单,只要解决一个Select抓回一棵树的问题这个关键问题,然后排序一下就搞定了。


你如何1条Select就抓回一颗树呢?如果父子关系只有主外键关联来表达,没有其他附加的表征字段的话,除了Oracle的自己的start with ... connect by...之外,我想不出来有什么一条SQL就能抓回整个子树。


用空间来换时间
比如为每个node增加一个lft/rgt,然后从上到下编号,这样就可以用一个select抓回所有纪录,某个节点的所有子节点是 "&gt;lft AND &lt;rgt" 的.
  缺点是增加纪录的时候稍微繁琐一些,需要多个SQL,但是大数据量的时候效率很高。


如果
数据库批量插入
数据库批量非连续删除
岂不是很痛苦?

用parent/child可以解决tree啊   至少我这里的树状菜单是这样的
0 请登录后投票
   发表时间:2004-03-26  
BTW:用一句SQL抓树  以前没有考虑过   都是在程序里用递归来实现的   想mysql这种查询很快的DB下  还是很舒服的
0 请登录后投票
   发表时间:2004-03-26  
比如父结点的编号是001,则子节点的编号可能是001001,001002...
编号不一定就要是主键,不过索引还是应该建的。
0 请登录后投票
   发表时间:2004-03-28  
hibernate的一对多有lazy属性,设它为true,这样可以在需要子结点数据的时候hibernate才发送sql语句去取。
0 请登录后投票
   发表时间:2004-03-30  
应该对Id进行编码,直接用ID表示层的关系,这样只要树的深度不是很高就可以了
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics