这次把常用的三种数据关系配置用例子给出,方便以后直接参考。
这次的配置是:SharpDevelop3.0beta, sql server 2k和nhibernate2.0GA版, 测试用的NUnit2.4.7版。
示例下载:
http://download.csdn.net/source/596685
新建一个项目,命名为Demo3。
加入引用,有NHiberanet.dll和Iesi.Collection.dll,测试用的nunit.framwork.dll。
还是老规则,cs文件放在Domain目录下,hbm.xml放在Mappings目录下,因为这次都是小例子,所以都是全手工写的,没有用生成工具,代码和配置文件都很简单明了。
One-to-One
Person和Passport,代表一个人有一本护照(或者身份证),一对一,呵呵。
- public class Person
- {
- public Person()
- {
- }
- virtual public int ID {get; set;}
- virtual public int Age {get; set;}
- virtual public string Name {get; set;}
- virtual public Passport Passport {get; set;}
- }
- <?xml version="1.0"?>
- <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Demo3" namespace="Demo3.Domain">
- <class name="Person">
- <id name="ID">
- <generator class="native"/>
- </id>
- <property name="Age"/>
- <property name="Name"/>
- <one-to-one name="Passport" class="Passport" cascade="all"/>
- </class>
- </hibernate-mapping>
- public class Passport
- {
- public Passport()
- {
- }
- virtual public int ID {get; set;}
- virtual public string Expire {get;set;}
- virtual public Person Person{get;set;}
- }
- <?xml version="1.0"?>
- <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Demo3" namespace="Demo3.Domain">
- <class name="Passport">
- <id name="ID">
- <generator class="foreign">
- <param name="property">Person</param>
- </generator>
- </id>
- <property name="Expire"/>
- <one-to-one name="Person" class="Person" constrained="true"/>
- </class>
- </hibernate-mapping>
测试代码:
- [Test]
- public void TestAdd()
- {
- var person = new Person();
- person.Age = 25;
- person.Name = "abin";
- var passport = new Passport();
- passport.Expire = "never";
- person.Passport = passport;
- passport.Person = person;
- var session = HibernateFacotry.CurrentSession();
- var tran = session.BeginTransaction();
- session.Save(person);
- tran.Commit();
- }
One-to-Many
这个例子更明了,Parent和Child,一对多。
- public class Parent
- {
- public Parent()
- {
- }
- virtual public int ID{get;set;}
- virtual public ISet<Child> Children{get;set;}
- }
- <?xml version="1.0"?>
- <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Demo3" namespace="Demo3.Domain">
- <class name="Parent">
- <id name="ID">
- <generator class="native"/>
- </id>
- <set name="Children" cascade="all" lazy="true">
- <key column="parent_id"></key>
- <one-to-many class="Child"/>
- </set>
- </class>
- </hibernate-mapping>
- public class Child
- {
- public Child()
- {
- }
- virtual public int ID {get; set;}
- virtual public Parent Parent{get;set;}
- }
- <?xml version="1.0"?>
- <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Demo3" namespace="Demo3.Domain">
- <class name="Child">
- <id name="ID">
- <generator class="native"/>
- </id>
- <many-to-one name="Parent" column="parent_id" class="Parent"/>
- </class>
- </hibernate-mapping>
Many-to-Many
这个例子是教科书上的经典,学生选课,Student,Lesson,和student_lesson。但配置中最后一个表是不会出现的,它只是配置表,在数据库中有,但配置里面没有。
- public class Student
- {
- public Student()
- {
- lessons = new HashedSet<Lesson>();
- }
- virtual public int ID{get;set;}
- virtual public ISet<Lesson> lessons{get;set;}
- virtual public int age{get;set;}
- virtual public string name{get;set;}
- }
- <?xml version="1.0"?>
- <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Demo3" namespace="Demo3.Domain">
- <class name="Student">
- <id name="ID">
- <generator class="native"/>
- </id>
- <property name="name"/>
- <property name="age"/>
- <set name="lessons" table="student_lesson" lazy="true" inverse="false" cascade="save-update">
- <key column="student_id"></key>
- <many-to-many class="Lesson" column="lesson_id"></many-to-many>
- </set>
- </class>
- </hibernate-mapping>
- public class Lesson
- {
- public Lesson()
- {
- students = new HashedSet<Student>();
- }
- virtual public ISet<Student> students{get;set;}
- virtual public int ID{get;set;}
- virtual public string LessonName{get;set;}
- }
- <?xml version="1.0"?>
- <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Demo3" namespace="Demo3.Domain">
- <class name="Lesson">
- <id name="ID">
- <generator class="native"/>
- </id>
- <property name="LessonName"/>
- <set name="students" table="student_lesson" lazy="true" inverse="true" cascade="save-update">
- <key column="lesson_id"></key>
- <many-to-many class="Student" column="student_id"></many-to-many>
- </set>
- </class>
- </hibernate-mapping>
多对多的配置容易让人发晕,说明一下。Set里面的table指定的是配置表,Key里面的列是指在配置表里哪一列是可以确认本类的,比如这个例子里面,本类是Lesson,所以在配置表里面,lesson_id是用来确认本类数据的,而many-to-many指的是关系那边的类Student的情况,所以Student对应的列是student_id。另外一边是一样的,因为many2many是对等的。记得Key和many-to-many中的column都要写,这样生成的配置表才会正确。
测试一下
- [Test]
- public void TestMethod()
- {
- // TODO: Add your test.
- var lesson = new Lesson();
- var student = new Student();
- lesson.LessonName = "math";
- lesson.students.Add(student);
- student.age = 14;
- student.name = "afrid";
- student.lessons.Add(lesson);
- var session = HibernateFacotry.CurrentSession();
- var tran = session.BeginTransaction();
- session.Save(student);
- tran.Commit();
- HibernateFacotry.CloseSession();
- }
主控方也要设置一下,主控方是inverse为false的那方。不设的话NHibernate会生成四条sql,最后一条会重复写数据,当然就不正确了。