上一篇:NHibernate学习笔记(一):初识NHibernate
本文的内容:
1.介绍NH如何处理对象间one-to-ont的映射关系;
经验教训:
1.操作一对一关联关系中的一个对象时,得在程序中指定如何与另一个对象关联,如在Student类中写this.NativePlace.Student = this;
2.在为类写映射文件时,必须指定类的具体的名称空间,若则运行时会出现"找不到***映射文件"的问题;
这两点都困扰了我好长一段时间,应该要引起注意.
点击下载本文相关代码(可在上篇代码的基础上做修改)
one-to-one:
NH中处理一对一关联的方式有两种:
1.主键关联
2.惟一外键关联
本文使用主键关联处理一对一的关系。
主键关联不需要额外的表字段;两行是通过这种一对一关系相关联的,那么这两行就共享同样的主关键字值。所以如果你希望两个对象通过主键一对一关联,你必须确认它们被赋予同样的标识值!
持久化对象之间一对一的关联关系是通过one-to-one
元素定义的。
<
one-to-one
name
="propertyName"
(1)
class
="ClassName"
(2)
cascade
="all|none|save-update|delete"
(3)
constrained
="true|false"
(4)
outer-join
="true|false|auto"
(5)
property-ref
="propertyNameFromAssociatedClass"
(6)
access
="field|property|ClassName"
(7)
/>
以下是对one-to-one元素各属性的说明:
1.name:属性的名字
2.class:(可选 - 默认是通过反射得到的属性类型): 被关联的类的名字
3.cascade:(可选) 表明操作是否从父对象级联到被关联的对象
4.constrained:(可选) 表明该类对应的表对应的数据库表,和被关联的对象所对应的数据库表之间,通过一个外键引用对主键进行约束。这个选项影响
Save()
和
Delete()
在级联执行时的先后顺序(也在schema export tool中被使用)
5.outer-join:(可选 - 默认为
auto
):当设置
hibernate.use_outer_join
的时候,对这个关联允许外连接抓取
6.property-ref:(可选): 指定关联类的一个属性,这个属性将会和本外键相对应。如果没有指定,会使用对方关联类的主键
7.access:(可选 - defaults to
property
): NHibernate 用来访问属性的策略
本文所涉及的类说明:
其中BizObject、User、ObjectBroker、Sessions等四个类就是
NHibernate学习笔记(一):初识NHibernate这篇文章定义的。
Student类和NativePlace类是一对一的双向关联关系:类Student通过属性NativePlace关联类NativePlace;类NativePlace通过属性Student关联类Student。
类Student的代码如下:
using
System;
using
System.Collections.Generic;
using
System.Text;
![None.gif](/Images/OutliningIndicators/None.gif)
namespace
NHibernateTest
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
public class Student : User
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
fields#region fields
private NativePlace objNativePlace;
#endregion
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
constructors#region constructors
public Student()
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
objNativePlace = new NativePlace();
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public Student(int StudentID) : base(StudentID)
{ }
#endregion
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
properties#region properties
public NativePlace NativePlace
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return objNativePlace;
}
set
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
objNativePlace = value;
}
}
#endregion
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
methors#region methors
public bool addNewStudent()
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
try
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.NativePlace.Student = this;
this.Create();
return true;
}
catch (Exception e)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return false;
}
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
public bool deleteStudent()
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
try
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.NativePlace.Student = this;
this.Delete();
return true;
}
catch (Exception e)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return false;
}
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
public bool updateStudent()
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
try
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this.NativePlace.Student = this;
this.Update();
return true;
}
catch (Exception e)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return false;
}
}
#endregion
}
}
在每次操作Student对象时,都得指定NativePlace.Student,如:this.NativePlace.Student = this;如果没写这一行运行时会出现“could not find class:NativePlace”(我就在写卡了好久)
类NativePlace的代码如下:
using
System;
using
System.Collections.Generic;
using
System.Text;
![None.gif](/Images/OutliningIndicators/None.gif)
namespace
NHibernateTest
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
public class NativePlace : BizObject
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
fields#region fields
private int intNPID;
private string strCity;
private string strProvince;
private Student objStudent;
#endregion
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
properties#region properties
public int NPID
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return intNPID;
}
set
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
intNPID = value;
}
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
public Student Student
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return objStudent;
}
set
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
objStudent = value;
}
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
public string Province
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return strProvince;
}
set
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
strProvince = value;
}
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
public string City
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return strCity;
}
set
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
strCity = value;
}
}
#endregion
}
}
这两个类的定义相对于User类没有什么太大的区别,接下来介绍两个类的配置文件。
从UML来看,类NativePlace与类User之间是集合(构成)关系,即类NativePlace属于类Student的一部分,但不能独立存在,也就是说类NativePlace是依赖于类User的。
数据库脚本:
--
表Users:用于保存Student对象
Create
Table
[
Users
]
(
[
ID
]
int
identity
(
1
,
1
)
constraint
PK_UserID1
Primary
Key
,
[
UserName
]
varchar
(
20
)
not
null
,
[
Password
]
varchar
(
20
)
not
null
)
![None.gif](/Images/OutliningIndicators/None.gif)
--
表NativePlace:用于保存NativePlace对象
Create
Table
NativePlace
(
--
表NativePlace与表Users通过主键关联,则需保证两表的主键名一致
ID
int
Constraint
PK_NativePlaceID
Primary
Key
,
Province
varchar
(
50
),
City
varchar
(
50
)
)
类Student的映射文件:
<?
xml version="1.0" encoding="utf-8"
?>
<
hibernate-mapping
xmlns
="urn:nhibernate-mapping-2.0"
>
<
class
name
="NHibernateTest.Student,NHibernateTest"
table
="Users"
>
<
id
name
="UserID"
column
="ID"
type
="Int32"
unsaved-value
="0"
>
<
generator
class
="identity"
/>
</
id
>
<
property
name
="UserName"
column
="UserName"
type
="String"
length
="20"
/>
<
property
name
="Password"
column
="Password"
type
="String"
length
="20"
/>
<
one-to-one
name
="NativePlace"
class
="NHibernateTest.NativePlace,NHibernateTest"
cascade
="all"
/>
</
class
>
</
hibernate-mapping
>
类NativePlace的映射文件:
<?
xml version="1.0" encoding="utf-8"
?>
<
hibernate-mapping
xmlns
="urn:nhibernate-mapping-2.0"
>
<
class
name
="NHibernateTest.NativePlace,NHibernateTest"
table
="NativePlace"
>
<
id
name
="NPID"
column
="ID"
type
="Int32"
unsaved-value
="0"
>
<
generator
class
="foreign"
>
<
param
name
="property"
>
Student
</
param
>
</
generator
>
</
id
>
<
property
name
="Province"
column
="Province"
type
="String"
length
="50"
/>
<
property
name
="City"
column
="City"
type
="String"
length
="50"
/>
<
one-to-one
name
="Student"
class
="NHibernateTest.Student,NHibernateTest"
cascade
="all"
constrained
="true"
></
one-to-one
>
</
class
>
</
hibernate-mapping
>
注意:如果采用<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">这种声明的话,请在之后指写相关联类的名字时请指出完整的类名(名称空间+类名)和程序集名:如<class name="NHibernateTest.NativePlace,NHibernateTest" table="NativePlace">和<one-to-one name="Student" class="NHibernateTest.Student,NHibernateTest" cascade="all" constrained="true"></one-to-one>
接下来是测试类:
using
System;
using
System.Collections.Generic;
using
System.ComponentModel;
using
System.Data;
using
System.Drawing;
using
System.Text;
using
System.Windows.Forms;
![None.gif](/Images/OutliningIndicators/None.gif)
namespace
NHibernateTest
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
public partial class frmStudent : Form
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
public frmStudent()
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
InitializeComponent();
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
Student objStudent;
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
//Add New Student
private void button1_Click(object sender, EventArgs e)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
objStudent = new Student();
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
objStudent.UserName = "jailu";
objStudent.Password = "123";
objStudent.NativePlace.Province = "FuJian";
objStudent.NativePlace.City = "LongYan";
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
if (objStudent.addNewStudent())
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
MessageBox.Show("Success");
}
else
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
MessageBox.Show("UnSuccess");
}
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
//Update
private void btnUpdate_Click(object sender, EventArgs e)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
objStudent.UserName = "Update UserName";
objStudent.NativePlace.Province = "Update Province";
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
if (objStudent.updateStudent())
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
MessageBox.Show("Success");
}
else
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
MessageBox.Show("UnSuccess");
}
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
//Delete
private void btnDelete_Click(object sender, EventArgs e)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (objStudent.deleteStudent())
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
MessageBox.Show("Success");
}
else
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
MessageBox.Show("UnSuccess");
}
}
}
}
所有的类和映射文件都写好了,运行...成功.