畅享博客 > 非鱼评影 > 程序设计 > NHibernate处理单表映射(自关联)
2006-3-25 14:34:34

NHibernate处理单表映射(自关联)

项目描述:一个极其简单的数据库,包括一个Groups表,有三个字段,GroupID(自增长的数字型,关键字),GroupName, ParentID,一个组可能有子组,或者没有。所以ParentID是可以为空的。一个Items表,有三个字段,ItemID(自增长的数字型,关键字),ItemName,GroupID。一个字段只属于一个组。

建立类文件,Group类包括两个必须字段GroupID和GroupName,另外还有一个ParentGroup字段,是Group类型的,对应它自己的父类,一个Items字段,是ISet类型的,对应它的Item,一个ChildGroups字段,也是ISet类型,对应它的下级组。Item类包括两个必须的字段ItemID和ItemName,还有一个Group类型的Group字段,对应它所属的Group。

接下来写对应的hbm.xml文件,Item的还是比较简单,一个ID,一个Name描述,一个Many-TO-One,对应它的组,可以设成允许所有级联操作。Group的就比较麻烦一些,一个ID,一个Name描述,另外还有三项:

一个One-To-Many的字段对应它的Items,以便找到Item,可以允许所有级联操作,设成lazy="true",因为我们通常并不需要在获取组的时候同时获取所有的Item。

一个One-To-Many的字段对应它的ChildGroups,以便找到下级Group,通常允许Delete级联就行了,(设成All可能会比较麻烦,没有仔细研究,参考别人的文章设的)。

一个Many-To-One的字段对应它的ParentGroup,以便连接它的父组,这里有一个允许为空的设置要设为true,因为第一级的组它的Parent是空的。

然后写测试代码,Group g=new Group(); g.GroupName="Some name"; session.Save(g); 保存好第一个组以后,可以继续生成它的子组,Group cg=new Group(); cg.GroupName="Another Name"; cg.ParentGroup=g; g.ChildGroups.Add(cg); session.Save(cg); 这样就可以保存进下一个组了。生成Item对象更简单了,跟前面的文章没有变化,Item的组可以是子类,也可以是父类,并没有关系。

检查了一下NHibernate所生成的SQL代码,当在数据库里提取出一个组对象的时候,首先是一个Select找到所指定ID的组(或者所有的组),然后使用这个ID找到它所有的子组,再对每一个子组再次调用一个Select找到更深的子组,直到它的子组个数为0为止。这样生成的SQL语句数量是相当可观的,不过在我的测试环境下,几十个组的反应速度还是相当快(Access),在可接受的范围,但是如果是大型网站上使用可能就要慎重一点了。

还想到一个问题,如果加一个收藏表,是所收藏的Group的ID或者Item的ID,它能不能跟那两个表建立自动的关联呢?想想好像不太可能,恐怕还是自己处理这些关系会更简单一点,有待研究。另外,要想在Group组里提取正确的层级关系,第一个调用就不能让它自动提取所有的表了,而只能调用第一级的表,这里就要使用自定义的查询条件了。


推荐到鲜果:

评论


发布者 匿名用户
2008-3-5 11:46:08


您正在以 匿名用户 的身份发表评论  快速登录
(不得超过 50 个汉字)
       看不清,换一个
提示消息
(输入完内容可以直接按Ctrl+Enter提交)