该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2004-03-25
可是我们常常在实际中碰到这样的结构,比如部门结构,栏目结构.... 原来用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(树有几层就调几次) 有更高效的实现办法么? 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2004-03-25
引用 原来用JDBC来处理这些树结构比较简单,只要解决一个Select抓回一棵树的问题这个关键问题,然后排序一下就搞定了。
你如何1条Select就抓回一颗树呢?如果父子关系只有主外键关联来表达,没有其他附加的表征字段的话,除了Oracle的自己的start with ... connect by...之外,我想不出来有什么一条SQL就能抓回整个子树。 |
|
返回顶楼 | |
发表时间:2004-03-25
robbin 写道 引用 原来用JDBC来处理这些树结构比较简单,只要解决一个Select抓回一棵树的问题这个关键问题,然后排序一下就搞定了。
你如何1条Select就抓回一颗树呢?如果父子关系只有主外键关联来表达,没有其他附加的表征字段的话,除了Oracle的自己的start with ... connect by...之外,我想不出来有什么一条SQL就能抓回整个子树。 用空间来换时间 比如为每个node增加一个lft/rgt,然后从上到下编号,这样就可以用一个select抓回所有纪录,某个节点的所有子节点是 ">lft AND <rgt" 的. 缺点是增加纪录的时候稍微繁琐一些,需要多个SQL,但是大数据量的时候效率很高。 |
|
返回顶楼 | |
发表时间:2004-03-25
那你用Hibernate不也一样吗?增加两个表征层次和位置的属性,到时候,
where ... node.lft < AND node.gft > ... |
|
返回顶楼 | |
发表时间:2004-03-26
acdc:
引用 比如为每个node增加一个lft/rgt,然后从上到下编号,这样就可以用一个select抓回所有纪录,某个节点的所有子节点是 ">lft AND <rgt" 的.
能不能给一例子呢(完成的SQL,和数据进行说明),因为我想了解你这个方法,我觉得可能你这样子有一些情况可能不行(我只是猜想,因为我的智商有限,请原谅). 谢谢了(这样子大家又可以学到也(东西)了) |
|
返回顶楼 | |
发表时间:2004-03-26
acdc 写道 robbin 写道 引用 原来用JDBC来处理这些树结构比较简单,只要解决一个Select抓回一棵树的问题这个关键问题,然后排序一下就搞定了。
你如何1条Select就抓回一颗树呢?如果父子关系只有主外键关联来表达,没有其他附加的表征字段的话,除了Oracle的自己的start with ... connect by...之外,我想不出来有什么一条SQL就能抓回整个子树。 用空间来换时间 比如为每个node增加一个lft/rgt,然后从上到下编号,这样就可以用一个select抓回所有纪录,某个节点的所有子节点是 ">lft AND <rgt" 的. 缺点是增加纪录的时候稍微繁琐一些,需要多个SQL,但是大数据量的时候效率很高。 如果 数据库批量插入 数据库批量非连续删除 岂不是很痛苦? 用parent/child可以解决tree啊 至少我这里的树状菜单是这样的 |
|
返回顶楼 | |
发表时间:2004-03-26
BTW:用一句SQL抓树 以前没有考虑过 都是在程序里用递归来实现的 想mysql这种查询很快的DB下 还是很舒服的
|
|
返回顶楼 | |
发表时间:2004-03-26
比如父结点的编号是001,则子节点的编号可能是001001,001002...
编号不一定就要是主键,不过索引还是应该建的。 |
|
返回顶楼 | |
发表时间:2004-03-28
hibernate的一对多有lazy属性,设它为true,这样可以在需要子结点数据的时候hibernate才发送sql语句去取。
|
|
返回顶楼 | |
发表时间:2004-03-30
应该对Id进行编码,直接用ID表示层的关系,这样只要树的深度不是很高就可以了
|
|
返回顶楼 | |