一、典型设置
cascade:(默认为none)级联。指明哪些操作会从对象级联到关联的对象。
inverse: (默认为false) 标记这个集合作为双向关联关系中的方向一端。在双向关联时才需要设置。在设为false的一端对cascade进行维护。处于性能的考虑,一般在数据少的一端或者被依赖端设置inverse="true",而让数据多的一段维护cascade。
1.one-to-one
1.1 数据库表结构
其中T_Person为主表,T_Employee为子表。T_Employee的PersonId参照T_Peson的PersonId。

1.2 示例映射类文件

/**//*
/*作者:DDL
/*联系:http://renrenqq.cnblogs.com/
*/

using System;

namespace DDLLY.TestNHibernate.TestAssociation.OneToOne


{

/**//// <summary>
///
/// </summary>
[Serializable]
public class Person

{

Private Members#region Private Members

private bool _isChanged;
private bool _isDeleted;
private int _personid;
private string _name;
private Employee _employee;

#endregion


Default ( Empty ) Class Constuctor#region Default ( Empty ) Class Constuctor


/**//// <summary>
/// default constructor
/// </summary>
public Person()

{
_personid = 0;
_name = null;
_employee = null;
}

#endregion // End of Default ( Empty ) Class Constuctor


Public Properties#region Public Properties


/**//// <summary>
///
/// </summary>
public virtual int PersonId

{

get
{ return _personid; }
set

{
_isChanged |= (_personid != value);
_personid = value;
}
}


/**//// <summary>
///
/// </summary>
public virtual string Name

{

get
{ return _name; }
set

{
if (value != null)
if (value.Length > 64)
throw new ArgumentOutOfRangeException("Invalid value for Name", value, value.ToString());

_isChanged |= (_name != value);
_name = value;
}
}


/**//// <summary>
///
/// </summary>
public Employee Employee

{

get
{ return _employee; }

set
{ _employee = value; }
}


/**//// <summary>
/// Returns whether or not the object has changed it's values.
/// </summary>
public bool IsChanged

{

get
{ return _isChanged; }
}


/**//// <summary>
/// Returns whether or not the object has changed it's values.
/// </summary>
public bool IsDeleted

{

get
{ return _isDeleted; }
}

#endregion


Public Functions#region Public Functions


/**//// <summary>
/// mark the item as deleted
/// </summary>
public void MarkAsDeleted()

{
_isDeleted = true;
_isChanged = true;
}

#endregion


Equals And HashCode Overrides#region Equals And HashCode Overrides


/**//// <summary>
/// local implementation of Equals based on unique value members
/// </summary>
public override bool Equals(object obj)

{
if (this == obj) return true;
if ((obj == null) || (obj.GetType() != GetType())) return false;
Person castObj = (Person) obj;
return (castObj != null) &&
(_personid == castObj.PersonId);
}


/**//// <summary>
/// local implementation of GetHashCode based on unique value members
/// </summary>
public override int GetHashCode()

{
int hash = 57;
hash = 27*hash*_personid.GetHashCode();
return hash;
}

#endregion
}
}

/**//*
/*作者:DDL
/*联系:http://renrenqq.cnblogs.com/
*/

using System;

namespace DDLLY.TestNHibernate.TestAssociation.OneToOne


{

/**//// <summary>
///
/// </summary>
[Serializable]
public class Employee

{

Private Members#region Private Members

private bool _isChanged;
private bool _isDeleted;
private int _personid;
private string _job;
private Person _person;

#endregion


Default ( Empty ) Class Constuctor#region Default ( Empty ) Class Constuctor


/**//// <summary>
/// default constructor
/// </summary>
public Employee()

{
_personid = 0;
_job = null;
_person = null;
}

#endregion // End of Default ( Empty ) Class Constuctor


Public Properties#region Public Properties


/**//// <summary>
///
/// </summary>
public virtual int PersonId

{

get
{ return _personid; }
set

{
_isChanged |= (_personid != value);
_personid = value;
}
}


/**//// <summary>
///
/// </summary>
public virtual string Job

{

get
{ return _job; }
set

{
if (value != null)
if (value.Length > 64)
throw new ArgumentOutOfRangeException("Invalid value for Job", value, value.ToString());

_isChanged |= (_job != value);
_job = value;
}
}

public Person Person

{

get
{ return _person; }

set
{ _person = value; }
}


/**//// <summary>
/// Returns whether or not the object has changed it's values.
/// </summary>
public bool IsChanged

{

get
{ return _isChanged; }
}


/**//// <summary>
/// Returns whether or not the object has changed it's values.
/// </summary>
public bool IsDeleted

{

get
{ return _isDeleted; }
}

#endregion


Public Functions#region Public Functions


/**//// <summary>
/// mark the item as deleted
/// </summary>
public void MarkAsDeleted()

{
_isDeleted = true;
_isChanged = true;
}

#endregion


Equals And HashCode Overrides#region Equals And HashCode Overrides


/**//// <summary>
/// local implementation of Equals based on unique value members
/// </summary>
public override bool Equals(object obj)

{
if (this == obj) return true;
if ((obj == null) || (obj.GetType() != GetType())) return false;
Employee castObj = (Employee) obj;
return (castObj != null) &&
(_personid == castObj.PersonId);
}


/**//// <summary>
/// local implementation of GetHashCode based on unique value members
/// </summary>
public override int GetHashCode()

{
int hash = 57;
hash = 27*hash*_personid.GetHashCode();
return hash;
}

#endregion
}
}
1.3 示例映射文件
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
<class name="DDLLY.TestNHibernate.TestAssociation.OneToOne.Person,DDLLY.TestNHibernate.TestAssociation" table="T_Person">

<id name="PersonId" column="PersonId" type="Int32" unsaved-value="0">
<generator class="native"/>
</id>
<property column="Name" type="String" name="Name" length="64" />

<one-to-one name="Employee" class="DDLLY.TestNHibernate.TestAssociation.OneToOne.Employee,DDLLY.TestNHibernate.TestAssociation" cascade="all"></one-to-one>
</class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
<class name="DDLLY.TestNHibernate.TestAssociation.OneToOne.Employee,DDLLY.TestNHibernate.TestAssociation" table="T_Employee">

<id name="PersonId" column="PersonId" type="Int32" unsaved-value="0">
<generator class="foreign">
<param name="property">Person</param>
</generator>
</id>
<property column="Job" type="String" name="Job" length="64" />

<one-to-one name="Person" class="DDLLY.TestNHibernate.TestAssociation.OneToOne.Person,DDLLY.TestNHibernate.TestAssociation" constrained="true"></one-to-one>
</class>
</hibernate-mapping>

1.4 说明
constrained(约束): 表明该类对应的表对应的数据库表,和被关联的对象所对应的数据库表之间,通过一个外键引用对主键进行约束。这个选项影响Save()和Delete()在级联执行时的先后顺序(也在schema export tool中被使用)。
property-ref: (可选) 指定关联类的一个属性,这个属性将会和本外键相对应。如果没有指定,会使用对方关联类的主键。
- <generator class="foreign">:表示使用另外一个相关联的对象的标识符,来创建主健。T_Employee的PersonId来自T_Person的ParentId。
Employee依赖于Person,所以通常在Person设置cascade。
2.另一种one-to-one
2.1数据库表结构
其中T_Person1为主表,T_Employee1为子表。T_Employee1的PersonId设置唯一约束,参照T_Person1的PersonId。

2.2示例映射类文件

/**//*
/*作者:DDL
/*联系:http://renrenqq.cnblogs.com/
*/

using System;

namespace DDLLY.TestNHibernate.TestAssociation.OneToOne1


{

/**//// <summary>
///
/// </summary>
[Serializable]
public class Person

{

Private Members#region Private Members

private bool _isChanged;
private bool _isDeleted;
private int _personid;
private string _name;
private Employee _employee;

#endregion


Default ( Empty ) Class Constuctor#region Default ( Empty ) Class Constuctor


/**//// <summary>
/// default constructor
/// </summary>
public Person()

{
_personid = 0;
_name = null;
_employee = null;
}

#endregion // End of Default ( Empty ) Class Constuctor


Public Properties#region Public Properties


/**//// <summary>
///
/// </summary>
public virtual int PersonId

{

get
{ return _personid; }
set

{
_isChanged |= (_personid != value);
_personid = value;
}
}


/**//// <summary>
///
/// </summary>
public virtual string Name

{

get
{ return _name; }
set

{
if (value != null)
if (value.Length > 64)
throw new ArgumentOutOfRangeException("Invalid value for Name", value, value.ToString());

_isChanged |= (_name != value);
_name = value;
}
}


/**//// <summary>
///
/// </summary>
public Employee Employee

{

get
{ return _employee; }

set
{ _employee = value; }
}


/**//// <summary>
/// Returns whether or not the object has changed it's values.
/// </summary>
public bool IsChanged

{

get
{ return _isChanged; }
}


/**//// <summary>
/// Returns whether or not the object has changed it's values.
/// </summary>
public bool IsDeleted

{

get
{ return _isDeleted; }
}

#endregion


Public Functions#region Public Functions


/**//// <summary>
/// mark the item as deleted
/// </summary>
public void MarkAsDeleted()

{
_isDeleted = true;
_isChanged = true;
}

#endregion


Equals And HashCode Overrides#region Equals And HashCode Overrides


/**//// <summary>
/// local implementation of Equals based on unique value members
/// </summary>
public override bool Equals(object obj)

{
if (this == obj) return true;
if ((obj == null) || (obj.GetType() != GetType())) return false;
Person castObj = (Person) obj;
return (castObj != null) &&
(_personid == castObj.PersonId);
}


/**//// <summary>
/// local implementation of GetHashCode based on unique value members
/// </summary>
public override int GetHashCode()

{
int hash = 57;
hash = 27*hash*_personid.GetHashCode();
return hash;
}

#endregion
}
}

/**//*
/*作者:DDL
/*联系:http://renrenqq.cnblogs.com/
*/

using System;

namespace DDLLY.TestNHibernate.TestAssociation.OneToOne1


{

/**//// <summary>
///
/// </summary>
[Serializable]
public class Employee

{

Private Members#region Private Members

private bool _isChanged;
private bool _isDeleted;
private int _employeeId;
private string _job;
private Person _person;

#endregion


Default ( Empty ) Class Constuctor#region Default ( Empty ) Class Constuctor


/**//// <summary>
/// default constructor
/// </summary>
public Employee()

{
_employeeId = 0;
_job = null;
_person = null;
}

#endregion // End of Default ( Empty ) Class Constuctor


Public Properties#region Public Properties


/**//// <summary>
///
/// </summary>
public virtual int EmployeeId

{

get
{ return _employeeId; }
set

{
_isChanged |= (_employeeId != value);
_employeeId = value;
}
}


/**//// <summary>
///
/// </summary>
public virtual string Job

{

get
{ return _job; }
set

{
if (value != null)
if (value.Length > 64)
throw new ArgumentOutOfRangeException("Invalid value for Job", value, value.ToString());

_isChanged |= (_job != value);
_job = value;
}
}

public Person Person

{

get
{ return _person; }

set
{ _person = value; }
}


/**//// <summary>
/// Returns whether or not the object has changed it's values.
/// </summary>
public bool IsChanged

{

get
{ return _isChanged; }
}


/**//// <summary>
/// Returns whether or not the object has changed it's values.
/// </summary>
public bool IsDeleted

{

get
{ return _isDeleted; }
}

#endregion


Public Functions#region Public Functions


/**//// <summary>
/// mark the item as deleted
/// </summary>
public void MarkAsDeleted()

{
_isDeleted = true;
_isChanged = true;
}

#endregion


Equals And HashCode Overrides#region Equals And HashCode Overrides


/**//// <summary>
/// local implementation of Equals based on unique value members
/// </summary>
public override bool Equals(object obj)

{
if (this == obj) return true;
if ((obj == null) || (obj.GetType() != GetType())) return false;
Employee castObj = (Employee) obj;
return (castObj != null) &&
(_employeeId == castObj.EmployeeId);
}


/**//// <summary>
/// local implementation of GetHashCode based on unique value members
/// </summary>
public override int GetHashCode()

{
int hash = 57;
hash = 27*hash*_employeeId.GetHashCode();
return hash;
}

#endregion
}
}
2.3示例映射文件
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
<class name="DDLLY.TestNHibernate.TestAssociation.OneToOne1.Person,DDLLY.TestNHibernate.TestAssociation" table="T_Person1">

<id name="PersonId" column="PersonId" type="Int32" unsaved-value="0">
<generator class="native"/>
</id>
<property column="Name" type="String" name="Name" length="64" />

<one-to-one name="Employee" class="DDLLY.TestNHibernate.TestAssociation.OneToOne1.Employee,DDLLY.TestNHibernate.TestAssociation" cascade="all"></one-to-one>
</class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
<class name="DDLLY.TestNHibernate.TestAssociation.OneToOne1.Employee,DDLLY.TestNHibernate.TestAssociation" table="T_Employee1">

<id name="EmployeeId" column="EmployeeId" type="Int32" unsaved-value="0">
<generator class="native"/>
</id>
<property column="Job" type="String" name="Job" length="64" />

<many-to-one name="Person" class="DDLLY.TestNHibernate.TestAssociation.OneToOne1.Person,DDLLY.TestNHibernate.TestAssociation" column="PersonId" unique="true"></many-to-one>
</class>
</hibernate-mapping>

2.4说明
这种one-to-one实际上是一种特殊的one-to-many,如果T_Employee1的PersonId不设置唯一约束,则可成为one-to-many。所以在T_Employee端设置many-to-one而不是one-to-one,记住要加上unique="true"表示唯一约束。
3.one-to-many
3.1 数据库表结构
T_Parent为主表,T_Child的ParentId参照T_Parent的ParentId。

注意:对于单向的one-to-many映射,cascade过程中会用到把T_Child表的ParentId设置为Null,所以ParentId应设为允许NULL;
而双向one-to-many映射,建议把T_Child的ParentI设置为不允许NULL
3.2 示例映射类文件(单向)

/**//*
/*作者:DDL
/*联系:http://renrenqq.cnblogs.com/
*/

using System;
using System.Collections;

namespace DDLLY.TestNHibernate.TestAssociation.OneToMany1


{

/**//// <summary>
///
/// </summary>
[Serializable]
public class Parent

{

Private Members#region Private Members

private bool _isChanged;
private bool _isDeleted;
private int _parentid;
private string _name;
private IList _children;

#endregion


Default ( Empty ) Class Constuctor#region Default ( Empty ) Class Constuctor


/**//// <summary>
/// default constructor
/// </summary>
public Parent()

{
_parentid = 0;
_name = null;
_children = new ArrayList();
}

#endregion // End of Default ( Empty ) Class Constuctor


Public Properties#region Public Properties


/**//// <summary>
///
/// </summary>
public virtual int ParentId

{

get
{ return _parentid; }
set

{
_isChanged |= (_parentid != value);
_parentid = value;
}
}


/**//// <summary>
///
/// </summary>
public virtual string Name

{

get
{ return _name; }
set

{
if (value != null)
if (value.Length > 64)
throw new ArgumentOutOfRangeException("Invalid value for Name", value, value.ToString());

_isChanged |= (_name != value);
_name = value;
}
}


/**//// <summary>
///
/// </summary>
public virtual IList Children

{

get
{ return _children; }
set

{
_isChanged |= (_children != value);
_children = value;
}
}


/**//// <summary>
/// Returns whether or not the object has changed it's values.
/// </summary>
public bool IsChanged

{

get
{ return _isChanged; }
}


/**//// <summary>
/// Returns whether or not the object has changed it's values.
/// </summary>
public bool IsDeleted

{

get
{ return _isDeleted; }
}

#endregion


Public Functions#region Public Functions


/**//// <summary>
/// mark the item as deleted
/// </summary>
public void MarkAsDeleted()

{
_isDeleted = true;
_isChanged = true;
}

#endregion


Equals And HashCode Overrides#region Equals And HashCode Overrides


/**//// <summary>
/// local implementation of Equals based on unique value members
/// </summary>
public override bool Equals(object obj)

{
if (this == obj) return true;
if ((obj == null) || (obj.GetType() != GetType())) return false;
Parent castObj = (Parent) obj;
return (castObj != null) &&
(_parentid == castObj.ParentId);
}


/**//// <summary>
/// local implementation of GetHashCode based on unique value members
/// </summary>
public override int GetHashCode()

{
int hash = 57;
hash = 27*hash*_parentid.GetHashCode();
return hash;
}

#endregion
}
}

/**//*
/*作者:DDL
/*联系:http://renrenqq.cnblogs.com/
*/

using System;

namespace DDLLY.TestNHibernate.TestAssociation.OneToMany1


{

/**//// <summary>
///
/// </summary>
[Serializable]
public class Child

{

Private Members#region Private Members

private bool _isChanged;
private bool _isDeleted;
private int _childid;
private string _name;
private int _parentid;

#endregion


Default ( Empty ) Class Constuctor#region Default ( Empty ) Class Constuctor


/**//// <summary>
/// default constructor
/// </summary>
public Child()

{
_childid = 0;
_name = null;
_parentid = 0;
}

#endregion // End of Default ( Empty ) Class Constuctor


Public Properties#region Public Properties


/**//// <summary>
///
/// </summary>
public virtual int ChildId

{

get
{ return _childid; }
set

{
_isChanged |= (_childid != value);
_childid = value;
}
}


/**//// <summary>
///
/// </summary>
public virtual string Name

{

get
{ return _name; }
set

{
if (value != null)
if (value.Length > 64)
throw new ArgumentOutOfRangeException("Invalid value for Name", value, value.ToString());

_isChanged |= (_name != value);
_name = value;
}
}


/**//// <summary>
///
/// </summary>
public virtual int ParentId

{

get
{ return _parentid; }
set

{
_isChanged |= (_parentid != value);
_parentid = value;
}
}


/**//// <summary>
/// Returns whether or not the object has changed it's values.
/// </summary>
public bool IsChanged

{

get
{ return _isChanged; }
}


/**//// <summary>
/// Returns whether or not the object has changed it's values.
/// </summary>
public bool IsDeleted

{

get
{ return _isDeleted; }
}

#endregion


Public Functions#region Public Functions


/**//// <summary>
/// mark the item as deleted
/// </summary>
public void MarkAsDeleted()

{
_isDeleted = true;
_isChanged = true;
}

#endregion


Equals And HashCode Overrides#region Equals And HashCode Overrides


/**//// <summary>
/// local implementation of Equals based on unique value members
/// </summary>
public override bool Equals(object obj)

{
if (this == obj) return true;
if ((obj == null) || (obj.GetType() != GetType())) return false;
Child castObj = (Child) obj;
return (castObj != null) &&
(_childid == castObj.ChildId);
}


/**//// <summary>
/// local implementation of GetHashCode based on unique value members
/// </summary>
public override int GetHashCode()

{
int hash = 57;
hash = 27*hash*_childid.GetHashCode();
return hash;
}

#endregion
}
}
3.3 示例映射文件(单向)
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
<class name="DDLLY.TestNHibernate.TestAssociation.OneToMany1.Parent,DDLLY.TestNHibernate.TestAssociation" table="T_Parent">

<id name="ParentId" column="ParentId" type="Int32" unsaved-value="0">
<generator class="native"/>
</id>
<property column="Name" type="String" name="Name" length="64" />
<bag name="Children" cascade="all" lazy="true">
<key column="ParentId"/>
<one-to-many class="DDLLY.TestNHibernate.TestAssociation.OneToMany1.Child,DDLLY.TestNHibernate.TestAssociation"/>
</bag>
</class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
<class name="DDLLY.TestNHibernate.TestAssociation.OneToMany1.Child,DDLLY.TestNHibernate.TestAssociation" table="T_Child">

<id name="ChildId" column="ChildId" type="Int32" unsaved-value="0">
<generator class="native"/>
</id>
<property column="Name" type="String" name="Name" length="64" />
<property column="ParentId" type="Int32" name="ParentId"/>
</class>
</hibernate-mapping>

3.4 示例映射类文件(双向)

/**//*
/*作者:DDL
/*联系:http://renrenqq.cnblogs.com/
*/

using System;
using System.Collections;

namespace DDLLY.TestNHibernate.TestAssociation.OneToMany


{

/**//// <summary>
///
/// </summary>
[Serializable]
public class Parent

{

Private Members#region Private Members

private bool _isChanged;
private bool _isDeleted;
private int _parentid;
private string _name;
private IList _children;

#endregion


Default ( Empty ) Class Constuctor#region Default ( Empty ) Class Constuctor


/**//// <summary>
/// default constructor
/// </summary>
public Parent()

{
_parentid = 0;
_name = null;
_children = new ArrayList();
}

#endregion // End of Default ( Empty ) Class Constuctor


Public Properties#region Public Properties


/**//// <summary>
///
/// </summary>
public virtual int ParentId

{

get
{ return _parentid; }
set

{
_isChanged |= (_parentid != value);
_parentid = value;
}
}


/**//// <summary>
///
/// </summary>
public virtual string Name

{

get
{ return _name; }
set

{
if (value != null)
if (value.Length > 64)
throw new ArgumentOutOfRangeException("Invalid value for Name", value, value.ToString());

_isChanged |= (_name != value);
_name = value;
}
}


/**//// <summary>
///
/// </summary>
public virtual IList Children

{

get
{ return _children; }
set

{
_isChanged |= (_children != value);
_children = value;
}
}


/**//// <summary>
/// Returns whether or not the object has changed it's values.
/// </summary>
public bool IsChanged

{

get
{ return _isChanged; }
}


/**//// <summary>
/// Returns whether or not the object has changed it's values.
/// </summary>
public bool IsDeleted

{

get
{ return _isDeleted; }
}

#endregion


Public Functions#region Public Functions


/**//// <summary>
/// mark the item as deleted
/// </summary>
public void MarkAsDeleted()

{
_isDeleted = true;
_isChanged = true;
}

#endregion


Equals And HashCode Overrides#region Equals And HashCode Overrides


/**//// <summary>
/// local implementation of Equals based on unique value members
/// </summary>
public override bool Equals(object obj)

{
if (this == obj) return true;
if ((obj == null) || (obj.GetType() != GetType())) return false;
Parent castObj = (Parent) obj;
return (castObj != null) &&
(_parentid == castObj.ParentId);
}


/**//// <summary>
/// local implementation of GetHashCode based on unique value members
/// </summary>
public override int GetHashCode()

{
int hash = 57;
hash = 27*hash*_parentid.GetHashCode();
return hash;
}

#endregion
}
}

/**//*
/*作者:DDL
/*联系:http://renrenqq.cnblogs.com/
*/

using System;

namespace DDLLY.TestNHibernate.TestAssociation.OneToMany


{

/**//// <summary>
///
/// </summary>
[Serializable]
public class Child

{

Private Members#region Private Members

private bool _isChanged;
private bool _isDeleted;
private int _childid;
private string _name;
private Parent _parent;

#endregion


Default ( Empty ) Class Constuctor#region Default ( Empty ) Class Constuctor


/**//// <summary>
/// default constructor
/// </summary>
public Child()

{
_childid = 0;
_name = null;
_parent = null;
}

#endregion // End of Default ( Empty ) Class Constuctor


Public Properties#region Public Properties


/**//// <summary>
///
/// </summary>
public virtual int ChildId

{

get
{ return _childid; }
set

{
_isChanged |= (_childid != value);
_childid = value;
}
}


/**//// <summary>
///
/// </summary>
public virtual string Name

![]()