Nibernate映射配置,简单记法,配置说明。
学时主要是看的博客和文档
博客地址 http://www.cnblogs.com/GoodHelper/archive/2011/02/14/nhiberante_01.html 本文中部分代码和图便是从这里复制过来的。
说出来有点丢人,一直只是会照猫画虎的配,理解总是差了一线,但想找到”规律“,再一次瞪眼过程中,终于把那一线过了,再之后就不用记什么,闭着眼都能配了。
这里用文字,颜色,少量的文档说明,结合实例,解析每种配置实例。
相信对刚学习hibernate的同学会有帮助。
总结如下
基本映射就不多说了 属性生成器搞定,主键必要时再查,联合主键很少会用到。
多对一映射
PS 大学学数据库是学过外键的,但.NET的培训和我几个上司的建议是不用外键,不过必要的时候我还是加了点……还加了级联和触发器
因为很少用,刚开始接触hibernate,外键一段时间还比较晕,可能有和我一样晕的
这里补充
一句话:外键表的外键是主键表的主键,结合下面的图,很好记,主外键关系,一般是多对一关系,分主键表,和外键表,外键表为多,主键表为一。
举例
stuent是外键表,class是主键表
public class Class { public virtual int? ID { get; set; } public virtual string Name { get; set; } } public class Student { public virtual int? ID { get; set; } public virtual string Name { get; set; } public virtual Class Class { get; set; } }
name属性名,class主键表对应的类,colum外键表的外键,property_ref 外键表的外键对应类的属性,默认为主键。
闭着眼睛写
映射关系为 :本类型Student的属性class ,对应的类型为Class,对应关系,本类型(Student)对应的表(student)的外键字段ClassID值=Class类的主键属性ID的值。
<class name="Student">
<many-to-one name="class" class="Class" column="ClassID" property-ref="ID"/>
</class>
这是详细的写法,可以加深理解。
默认值可以简写为
<many-to-one name="Class" column="ClassID"/>
简写是因为有默认值
class(可选 - 默认是通过反射得到属性类型): 关联的类的名字,反射可以找到对应的类型
property-ref: (可选) 指定关联类的一个属性,这个属性将会和本外键相对应。 如果没有指定,会使用对方关联类的主键。 就是说 关联的如果是对方的主键就可以不写本项。
下面是文档的原话
property-ref属性只应该用来对付老旧的数据库系统, 可能有外键指向对方关联表的是个非主键字段(但是应该是一个惟一关键字)的情况下。 这是一种十分丑陋的关系模型。比如说,假设Product类有一个惟一的序列号, 它并不是主键。(unique属性控制NHibernate通过SchemaExport工具生成DDL的过程。)
但若property-ref指向对方的主键就不是丑陋的关系模型了。
一对多
还是之前的关系图,与多对一对应
public class Student { public virtual int? ID { get; set; } public virtual string Name { get; set; } } public class Class { public virtual int? ID { get; set; } public virtual string Name { get; set; } public virtual IList<Student> Students { get; set; } }
一个班级可能有多个学生,学生是个集合ILIST
一对多关系 和 一对一关系中,一的一方,与其他类对应的属性(字段)默认且必须为该类型的ID(表的主键),这个例子为Class类的ID。
本类型(Class)的主键ID 1——m 一对多的集合(IList<Student>)里每个元素(Students)所对应表(Student)的外键(ClassID)
<class name="Class" table="T_Class" lazy="true" >
<id name="ID" type="int" column="ClassID"> 这个ClassID只是配置Class类的主键
<generator class="native"/>
</id>
<bag name="Students">
<key column="ClassID"/> 这个ClassID实际是指Student类对应的Student表的字段。
<one-to-many class="Student"/>
</bag>
</class>
一对多和多对一就此结束,只有一对多,或只有多对一,为单向,都有则为双向,双向就不多说了,结合一对多和多对一便可以得到结果。
一对一
还是上面那句
一对多关系 和 一对一关系中,一的一方,与其他类对应的属性(字段)默认且必须为该类型的ID属性(表的主键)。
补充 一的一方指主动配置的一方,也就是映射文件里有one-to-one配置的一方。
一、单向主键关联映射
这种关系关联配置上没什么新东西,主要是主键的配置
主键关联不需要额外的表字段;如果两行是通过这种一对一关系相关联的,那么这两行就共享同样的主关键字值。所以如果你希望两个对象通过主键一对一关联,你必须确认它们被赋予同样的标识值!
<class name="Person" table="PERSON"> <id name="Id" column="PERSON_ID"> <generator class="foreign"> <param name="property">Employee</param> ,主键值 配置为通过外键查询,Person的主键值=Exmloyee类的主键值 </generator> </id> ... <one-to-one name="Employee" class="Employee" constrained="true"/> 映射关系:无视上面的主键配置,这节的意思是,Person的主键Id=属性Employee的主键,one-to-one 也有property-ref这项,如果是主键则可省,唯一主外键一对一映射就设置了这项。
</class>
上面为单向一对一。
双向只要在Employee类里加Person属性,映射里添
<one-to-one name="Person" class="Person"/>
就OK了,Emplyee的主键ID=Employee类中Person属性的ID。
用
<many-to-one name="Person" class="Person" column="PERSON_ID" unique="true"/> 也可以实现相同的效果,unique="true"表示是一对一,column="PERSON_ID"表示是Employee的PERSON_ID 对应的Person类的主键。
唯一外键关联映射
单向。
<many-to-one name="Person" class="Person" column="PERSON_ID" unique="true"/>
如果在Person的映射加入下面几句,这种关联就是双向的:
<one-to-one name="Employee" class="Employee" property-ref="Person"/>
Person类主键ID=Employee类的Person属性的主键ID
多对多 hibernate并不推荐配置多对多,实际上多对多是通过第三张表作为中间表实现关联的
多对多的配置,完全可以自配置表1和表2 表2二表3,这样,实现表1和表3的多对多关系。 这在EF里是显式的多对多。
而下面这种直接配置多对多关系,在EF对映的是隐式的多对多。
懂单向的多对多,双向的也是一个道理
多对多,关系,主动配置的一方,默认为ID属性(表的主键)。
User(T_User)的主键ID(UserID)=T_User_Role的UserID,T_User_Role的RoleID=Role(Role表)表的主键ID(RoleID)
<many-to-many class="Role" column="RoleID"/> 与上面的类似
//这个ROLE,默认关联ROLE的ID(主键)
之前的某些配轩,是主键则可以省略不写,不是主键则添加 property-ref配置,不过这个我没试过。
<class name="User" table="T_User" lazy="true" >
<id name="ID" type="int" column="UserID"> 这是User类配置的主键,与下面的关系配置无关,烟雾弹。
<generator class="native"/>
</id>
<bag name="Roles" table="T_User_Role">
<key column="UserID"/>
<many-to-many class="Role" column="RoleID"/>
</bag>
</class>