NHibernate支持树形结构的解决方法
在实际项目中,经常会碰到树状结构,比如模块菜单,组织架构等,典型的定义如下图:
对Nhibernate的tree map方法讲的比较详细,但是这种方法对于大数据量会有性能问题。我们更多的是用单表映射来完成实体类和表的一对一映射,如表
对于这种树状结构的表,实体类一般都需要有HasChild活着ChildCount属性来表示是否是叶子节点,NHibernate可以用下面的映射文件来实现。
<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" > <!-- 菜单定义 --> <class name="SysAdmin.BLL.Domain.Menu,SysAdmin.BLL" table="SYSMENU" lazy="false"> <!-- 主键 --> <id name="ID" column="ID"> <generator class="Sys.Core.DAO.IDGenerator,Sys.Core"> <param name="code">SYSPERMISSION.ID</param> </generator> </id> <!--菜单名 --> <property name="Name" column="NAME" /> <!--菜单父id--> <property name="ParentId" column="PARENTID" /> <!--<many-to-one name="Parent" class="SysAdmin.BLL.Domain.Menu,SysAdmin.BLL" column="PARENTID" />--> <!--菜单url--> <property name="Url" column="URL" /> <!--JS 函数--> <property name="JsFunc" column="JSFUNC" /> <property name="ChildCount" formula="(select count(*) from SYSMENU where SYSMENU.PARENTID=ID)"/> </class> </hibernate-mapping>
实体类为:
///namespace SysAdmin.BLL.Domain { /// <summary> /// 菜单定义类 /// </summary> public class Menu : DomainObject<Int32> { /// <summary> /// 菜单名 /// </summary> public string Name { get; set; } /// <summary> /// 父菜单节点 /// </summary> public Int32 ParentId { get; set; } /// <summary> /// 菜单url /// </summary> public string Url { get; set;} /// <summary> /// 触发的js函数 /// </summary> public string JsFunc { get; set;} public Int32 ChildCount { get; set; }public override int GetHashCode() { return (GetType().FullName + ID).GetHashCode(); } } }Spring.net 的测试类为
namespace SysAdmin.Test.DAO { [TestFixture] public class MenuDAOTests : AbstractDaoIntegrationTests { public IMenuDAO MenuDAO { get; set; } public ISessionFactory SessionFactory { get; set; } [Test] public void TestAddMenu() { Menu menu = new Menu(); menu.Name = "系统管理"; //menu.ParentId = -1; menu.Url = ""; menu.JsFunc = ""; Int32 pMenuIdRoot = (Int32)MenuDAO.Save(menu); SessionFactoryUtils.GetSession(SessionFactory, true).Flush(); menu = new Menu(); menu.Name = "用户管理"; menu.ParentId = pMenuIdRoot; MenuDAO.Save(menu); SessionFactoryUtils.GetSession(SessionFactory, true).Flush(); menu = new Menu(); menu.Name = "角色管理"; menu.ParentId = pMenuIdRoot; MenuDAO.Save(menu); SessionFactoryUtils.GetSession(SessionFactory, true).Flush(); menu = new Menu(); menu.Name = "组织架构"; menu.ParentId = pMenuIdRoot; MenuDAO.Save(menu); SessionFactoryUtils.GetSession(SessionFactory, true).Flush(); menu = new Menu(); menu.Name = "权限管理"; menu.ParentId = pMenuIdRoot; Int32 pMenuId = (Int32)MenuDAO.Save(menu); SessionFactoryUtils.GetSession(SessionFactory, true).Flush(); menu = new Menu(); menu.Name = "菜单权限"; menu.ParentId = pMenuId; MenuDAO.Save(menu); SessionFactoryUtils.GetSession(SessionFactory, true).Flush(); menu = new Menu(); menu.Name = "功能权限"; menu.ParentId = pMenuId; MenuDAO.Save(menu); SessionFactoryUtils.GetSession(SessionFactory, true).Flush(); //清理1级缓存,不清理不会触发select sql SessionFactoryUtils.GetSession(SessionFactory, true).Clear(); menu = MenuDAO.FindById(pMenuIdRoot); SessionFactoryUtils.GetSession(SessionFactory, true).Flush(); Assert.AreEqual("系统管理",menu.Name); Assert.AreEqual(4, menu.ChildCount ); menu = MenuDAO.FindById(pMenuId); Assert.AreEqual("权限管理",menu.Name); Assert.AreEqual( 2,menu.ChildCount); } } }