NHibernate的关联映射(one-to-one,one-to-many,many-to-many)以及cascade分析

2024-03-28 01:18

本文主要是介绍NHibernate的关联映射(one-to-one,one-to-many,many-to-many)以及cascade分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、典型设置

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
    
{
        
#region Private Members

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

        
#endregion


        
#region Default ( Empty ) Class Constuctor

        
/// <summary>
        
/// default constructor
        
/// </summary>

        public Person()
        
{
            _personid 
= 0;
            _name 
= null;
            _employee 
= null;
        }


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

        
#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


        
#region Public Functions

        
/// <summary>
        
/// mark the item as deleted
        
/// </summary>

        public void MarkAsDeleted()
        
{
            _isDeleted 
= true;
            _isChanged 
= true;
        }


        
#endregion


        
#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
    
{
        
#region Private Members

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

        
#endregion


        
#region Default ( Empty ) Class Constuctor

        
/// <summary>
        
/// default constructor
        
/// </summary>

        public Employee()
        
{
            _personid 
= 0;
            _job 
= null;
            _person 
= null;
        }


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

        
#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


        
#region Public Functions

        
/// <summary>
        
/// mark the item as deleted
        
/// </summary>

        public void MarkAsDeleted()
        
{
            _isDeleted 
= true;
            _isChanged 
= true;
        }


        
#endregion


        
#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
    
{
        
#region Private Members

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

        
#endregion


        
#region Default ( Empty ) Class Constuctor

        
/// <summary>
        
/// default constructor
        
/// </summary>

        public Person()
        
{
            _personid 
= 0;
            _name 
= null;
            _employee 
= null;
        }


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

        
#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


        
#region Public Functions

        
/// <summary>
        
/// mark the item as deleted
        
/// </summary>

        public void MarkAsDeleted()
        
{
            _isDeleted 
= true;
            _isChanged 
= true;
        }


        
#endregion


        
#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
    
{
        
#region Private Members

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

        
#endregion


        
#region Default ( Empty ) Class Constuctor

        
/// <summary>
        
/// default constructor
        
/// </summary>

        public Employee()
        
{
            _employeeId 
= 0;
            _job 
= null;
            _person 
= null;
        }


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

        
#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


        
#region Public Functions

        
/// <summary>
        
/// mark the item as deleted
        
/// </summary>

        public void MarkAsDeleted()
        
{
            _isDeleted 
= true;
            _isChanged 
= true;
        }


        
#endregion


        
#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
    
{
        
#region Private Members

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

        
#endregion


        
#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

        
#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


        
#region Public Functions

        
/// <summary>
        
/// mark the item as deleted
        
/// </summary>

        public void MarkAsDeleted()
        
{
            _isDeleted 
= true;
            _isChanged 
= true;
        }


        
#endregion


        
#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
    
{
        
#region Private Members

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

        
#endregion


        
#region Default ( Empty ) Class Constuctor

        
/// <summary>
        
/// default constructor
        
/// </summary>

        public Child()
        
{
            _childid 
= 0;
            _name 
= null;
            _parentid 
= 0;
        }


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

        
#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
 

        
#region Public Functions

        
/// <summary>
        
/// mark the item as deleted
        
/// </summary>

        public void MarkAsDeleted()
        
{
            _isDeleted 
= true;
            _isChanged 
= true;
        }


        
#endregion


        
#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
    
{
        
#region Private Members

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

        
#endregion


        
#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

        
#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


        
#region Public Functions

        
/// <summary>
        
/// mark the item as deleted
        
/// </summary>

        public void MarkAsDeleted()
        
{
            _isDeleted 
= true;
            _isChanged 
= true;
        }


        
#endregion


        
#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
    
{
        
#region Private Members

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

        
#endregion


        
#region Default ( Empty ) Class Constuctor

        
/// <summary>
        
/// default constructor
        
/// </summary>

        public Child()
        
{
            _childid 
= 0;
            _name 
= null;
            _parent 
= null;
        }


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

        
#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 Parent Parent
        
{
            
get return _parent; }
            
set
            
{
                _isChanged 
|= (_parent != value);
                _parent 
= 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
 

        
#region Public Functions

        
/// <summary>
        
/// mark the item as deleted
        
/// </summary>

        public void MarkAsDeleted()
        
{
            _isDeleted 
= true;
            _isChanged 
= true;
        }


        
#endregion


        
#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.5 示例映射类文件(双向)

 

<? xml version="1.0" encoding="utf-8"  ?>
< hibernate-mapping  xmlns ="urn:nhibernate-mapping-2.0" >
    
< class  name ="DDLLY.TestNHibernate.TestAssociation.OneToMany.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"  inverse ="true"  lazy ="true" >
      
< key  column ="ParentId" />
      
< one-to-many  class ="DDLLY.TestNHibernate.TestAssociation.OneToMany.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.OneToMany.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"   />
    
        
< many-to-one  name ="Parent"  column ="ParentId"  class ="DDLLY.TestNHibernate.TestAssociation.OneToMany.Parent,DDLLY.TestNHibernate.TestAssociation"   />
        
    
</ class >
</ hibernate-mapping >

3.6 说明

在NHibernate配置文件中使用<set>, <list>, <map>, <bag>, <array> 和 <primitive-array>等元素来定义集合。<bag>是典型的一个,代码中我们用IList和它对应。我们以后会详细讲集合这个话题。

lazy表示允许延迟加载。表示在需要使用时才加载需要的数据。例如使用lazy时我们Load一个Parent他的Children为空,只有我们访问它的某一个Child时数据才会被加载;而不设置lazy我们Load一个Parent时其Children将同时加载。注意:使用lazy加载必须保证对应ISession的打开,否则懒加载会失败。

one-to-many可以设置单向和双向映射,设置单向时Child一段不设置many-to-one,而设置了ParentId的属性。

双向映射需要设置inverse而单向不需要。

单项映射在cascade时会对把T_Child的ParentId使用Update为Null的操作。

建议尽量使用双向映射。

4.many-to-many

4.1 数据库表结构

4.2 示例映射类文件

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


using  System;
using  System.Collections;

namespace  DDLLY.TestNHibernate.TestAssociation.ManyToMany
{
    
/// <summary>
    
///    
    
/// </summary>

    [Serializable]
    
public class User
    
{
        
#region Private Members

        
private bool _isChanged;
        
private bool _isDeleted;
        
private int _userid;
        
private string _username;
        
private string _password;
        
private string _email;
        
private IList _roles;

        
#endregion


        
#region Default ( Empty ) Class Constuctor

        
/// <summary>
        
/// default constructor
        
/// </summary>

        public User()
        
{
            _userid 
= 0;
            _username 
= null;
            _password 
= null;
            _email 
= null;
            _roles 
= new ArrayList();
        }


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

        
#region Public Properties

        
/// <summary>
        
/// 
        
/// </summary>        

        public virtual int UserId
        
{
            
get return _userid; }
            
set
            
{
                _isChanged 
|= (_userid != value);
                _userid 
= value;
            }

        }


        
/// <summary>
        
/// 
        
/// </summary>        

        public virtual string UserName
        
{
            
get return _username; }
            
set
            
{
                
if (value != null)
                    
if (value.Length > 64)
                        
throw new ArgumentOutOfRangeException("Invalid value for UserName", value, value.ToString());

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

        }


        
/// <summary>
        
/// 
        
/// </summary>        

        public virtual string Password
        
{
            
get return _password; }
            
set
            
{
                
if (value != null)
                    
if (value.Length > 32)
                        
throw new ArgumentOutOfRangeException("Invalid value for Password", value, value.ToString());

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

        }


        
/// <summary>
        
/// 
        
/// </summary>        

        public virtual string Email
        
{
            
get return _email; }
            
set
            
{
                
if (value != null)
                    
if (value.Length > 64)
                        
throw new ArgumentOutOfRangeException("Invalid value for Email", value, value.ToString());

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

        }


        
public IList Roles
        
{
            
get return _roles; }
            
set { _roles = 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


        
#region Public Functions

        
/// <summary>
        
/// mark the item as deleted
        
/// </summary>

        public void MarkAsDeleted()
        
{
            _isDeleted 
= true;
            _isChanged 
= true;
        }


        
#endregion


        
#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;
            User castObj 
= (User) obj;
            
return (castObj != null&&
                   (_userid 
== castObj.UserId);
        }


        
/// <summary>
        
/// local implementation of GetHashCode based on unique value members
        
/// </summary>

        public override int GetHashCode()
        
{
            
int hash = 57;
            hash 
= 27*hash*_userid.GetHashCode();
            
return hash;
        }


        
#endregion

    }

}

 

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


using  System;
using  System.Collections;

namespace  DDLLY.TestNHibernate.TestAssociation.ManyToMany
{
    
/// <summary>
    
///    
    
/// </summary>

    [Serializable]
    
public class Role
    
{
        
#region Private Members

        
private bool _isChanged;
        
private bool _isDeleted;
        
private int _roleid;
        
private string _rolename;
        
private IList _users;

        
#endregion


        
#region Default ( Empty ) Class Constuctor

        
/// <summary>
        
/// default constructor
        
/// </summary>

        public Role()
        
{
            _roleid 
= 0;
            _rolename 
= null;
            _users 
= new ArrayList();
        }


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

        
#region Public Properties

        
/// <summary>
        
/// 
        
/// </summary>        

        public virtual int RoleId
        
{
            
get return _roleid; }
            
set
            
{
                _isChanged 
|= (_roleid != value);
                _roleid 
= value;
            }

        }


        
/// <summary>
        
/// 
        
/// </summary>        

        public virtual string RoleName
        
{
            
get return _rolename; }
            
set
            
{
                
if (value != null)
                    
if (value.Length > 64)
                        
throw new ArgumentOutOfRangeException("Invalid value for RoleName", value, value.ToString());

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

        }


        
public IList Users
        
{
            
get return _users; }
            
set { _users = 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


        
#region Public Functions

        
/// <summary>
        
/// mark the item as deleted
        
/// </summary>

        public void MarkAsDeleted()
        
{
            _isDeleted 
= true;
            _isChanged 
= true;
        }


        
#endregion


        
#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;
            Role castObj 
= (Role) obj;
            
return (castObj != null&&
                   (_roleid 
== castObj.RoleId);
        }


        
/// <summary>
        
/// local implementation of GetHashCode based on unique value members
        
/// </summary>

        public override int GetHashCode()
        
{
            
int hash = 57;
            hash 
= 27*hash*_roleid.GetHashCode();
            
return hash;
        }


        
#endregion

    }

}

4.3 示例映射文件

 

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

        
< id  name ="UserId"  column ="UserId"  type ="Int32"  unsaved-value ="0" >
            
< generator  class ="native" />
        
</ id >
        
< property  column ="UserName"  type ="String"  name ="UserName"  not-null ="true"  length ="64"   />
        
< property  column ="Password"  type ="String"  name ="Password"  not-null ="true"  length ="32"   />
        
< property  column ="Email"  type ="String"  name ="Email"  length ="64"   />

    
< bag  name ="Roles"  table ="T_User_Role"  lazy ="true" >
      
< key  column ="UserId" />
      
< many-to-many  class ="DDLLY.TestNHibernate.TestAssociation.ManyToMany.Role,DDLLY.TestNHibernate.TestAssociation"  column ="RoleId" />
    
</ bag >
        
    
</ class >
</ hibernate-mapping >

 

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

        
< id  name ="RoleId"  column ="RoleId"  type ="Int32"  unsaved-value ="0" >
            
< generator  class ="native" />
        
</ id >
        
< property  column ="RoleName"  type ="String"  name ="RoleName"  not-null ="true"  length ="64"   />

    
< bag  name ="Users"  table ="T_User_Role"  lazy ="true"  inverse ="true" >
      
< key  column ="RoleId" />
      
< many-to-many  class ="DDLLY.TestNHibernate.TestAssociation.ManyToMany.User,DDLLY.TestNHibernate.TestAssociation"  column ="UserId" />
    
</ bag >


  
</ class >
</ hibernate-mapping >

4.4 说明

many-to-many性能不佳,数据量大时应尽可能避免使用。并尽可能使用lazy="true"。

在数据量少的一端设置inverse="true",让数据量多的一段维护cascade。

二、cascade分析

1.总述

cascade:(默认为none)级联。指明哪些操作会从对象级联到关联的对象。

orphans:孤儿,没有夫对象的子对象。对于代码Child.Parent==null,对于数据库T_Child表中ParentId为Null的数据。

delete orphans表示cascade时删除孤儿。

一般系统中是不允许孤儿存在的,我们可以通过数据库的约束来限制孤儿,例如T_Child的ParentId设为Not NULL。

如果确实存在孤儿请考虑适合的cascade策略。

cascade类型对应操作

all

Save / Delete / Update

all-delete-orphan

Save / Delete / Update + delete orphans

delete-orphan

Delete + delete orphans

none

No Cascades

delete

Delete

save-update

Save / Update

 2.one-to-one

a.初始化数据

PersonIdNameJob
1DDL编程
2LLYNULL

b.测试方法

TestAddPersonWithAddEmployee

Person person  =   new  Person();
person.Name 
=   " newPerson " ;
Employee employee 
=   new  Employee();
employee.Job 
=   " newJob " ;
person.Employee 
=  employee;
employee.Person 
=  person;

session.Save(person);

TestUpdatePersonWithAddEmployee

Person person  =  session.Load( typeof  (Person),  2 as  Person;
person.Employee 
=   new  Employee();
person.Employee.Person 
=  person;
person.Employee.Job 
=   " LLYJob " ;

session.Update(person);

TestUpdatePersonWithUpdateEmployee

Person person  =  session.Load( typeof  (Person),  1 as  Person;
person.Employee.Job 
=   " DDL'New Job " ;

session.Update(person);

TestDeletePersonWithDeleteEmployee

Person person  =  session.Load( typeof  (Person),  1 as  Person;

session.Delete(person);

c.测试结果

测试方法

save-update

delete

delete-orphan

all

all-delete-orphan

none

TestAddPersonWithAddEmployee

Y

N

N

Y

Y

N

TestUpdatePersonWithAddEmployee

Y

N

N

Y

Y

N

TestUpdatePersonWithUpdateEmployee

Y

Y

Y

Y

Y

Y

TestDeletePersonWithDeleteEmployee

N

Y

Y

Y

Y

N

 2.另一种one-to-one

a.初始化数据

PersonIdNameEmployeeIdJob
1DDL1编程
2LLYNULLNULL

 b.测试方法

TestAddPersonWithAddEmployee

不支持

TestUpdatePersonWithAddEmployee

Person person  =  session.Load( typeof  (Person),  2 as  Person;
person.Employee 
=   new  Employee();
person.Employee.Person 
=  person;
person.Employee.Job 
=   " LLYJob " ;

session.Update(person);
session.Flush();

TestUpdatePersonWithUpdateEmployee

Person person  =  session.Load( typeof  (Person),  1 as  Person;
person.Employee.Job 
=   " DDL'New Job " ;

session.Update(person);
session.Flush();

 TestDeletePersonWithDeleteEmployee

Person person  =  session.Load( typeof  (Person),  1 as  Person;

session.Delete(person);
session.Flush();

c.测试结果

测试方法

save-update

delete

delete-orphan

all

all-delete-orphan

none

TestAddPersonWithAddEmployee

不支持

不支持

不支持

不支持

不支持

不支持

TestUpdatePersonWithAddEmployee

Y

N

N

Y

Y

N

TestUpdatePersonWithUpdateEmployee

Y

Y

Y

Y

Y

Y

TestDeletePersonWithDeleteEmployee

N

Y

Y

Y

Y

N

3.one-to-many(双向)

a.初始化数据

ParentIdParentNameChildIdChildName
1Parent11Child1
2Parent2NULLNULL

b.测试方法

TestAddParentWithAddChild

Parent parent  =   new  Parent();
parent.Name 
=   " NewParent " ;

Child child 
=   new  Child();
child.Name 
=   " NewChild " ;
child.Parent 
=  parent;

parent.Children.Add(child);

session.Save(parent);
session.Flush();

TestUpdateParentWithAddChild

Parent parent  =  session.Load( typeof  (Parent),  2 as  Parent;

Child child 
=   new  Child();
child.Name 
=   " NewChild " ;
child.Parent 
=  parent;

parent.Children.Add(child);

session.Update(parent);

session.Flush();

TestUpdateParentWithUpdateChild

Parent parent  =  session.Load( typeof  (Parent),  1 as  Parent;

Child child 
=  (Child) parent.Children[ 0 ];

child.Name 
=   " UpdateName " ;

session.Update(parent);

session.Flush();

TestDeleteParentWithChild

Parent parent  =  session.Load( typeof  (Parent),  1 as  Parent;

session.Delete(parent);
session.Flush();

 c.测试结果

测试方法

save-update

delete

delete-orphan

all

all-delete-orphan

none

TestAddParentWithAddChildYNNYYN
TestUpdateParentWithAddChildYNNYYN
TestUpdateParentWithUpdateChildYYYYYY
TestDeleteParentWithChildNYYYYN

4.one-to-many(单向)

a.初始化数据

同上

b.测试方法

TestAddParentWithAddChild

不支持

TestUpdateParentWithAddChild

Parent parent  =  session.Load( typeof  (Parent),  2 as  Parent;

Child child 
=   new  Child();
child.Name 
=   " NewChild " ;
child.ParentId 
=  parent.ParentId;

parent.Children.Add(child);

session.Update(parent);

session.Flush();

TestUpdateParentWithUpdateChild

Parent parent  =  session.Load( typeof  (Parent),  1 as  Parent;

Child child 
=  (Child) parent.Children[ 0 ];

child.Name 
=   " UpdateName " ;

session.Update(parent);

session.Flush();

TestDeleteParentWithChild

Parent parent  =  session.Load( typeof  (Parent),  1 as  Parent;

session.Delete(parent);

session.Flush();

 c.测试结果

测试方法

save-update

delete

delete-orphan

all

all-delete-orphan

none

TestAddParentWithAddChild不支持不支持不支持不支持不支持不支持
TestUpdateParentWithAddChildYNNYYN
TestUpdateParentWithUpdateChildYYYYYY
TestDeleteParentWithChildParent被删除,Child成为孤儿YYYYParent被删除,Child成为孤儿

5.many-to-many
many-to-many和别的关联映射有所不同。例子中:Role和User没有直接的依赖关系,而是通过一张中间表完成。在删除User时一般不会要求删除Role,而是删除之间的关系(即从中间表删除数据)。

a.初始化数据

UserIdUserNamePasswordEmailRoleIdRoleName
1DDL1NULL1角色1
1DDL1NULL2角色2
2LLY2NULL1角色1
3陌生人3NULLNULLNULL
NULLNULLNULLNULL3角色3

b.测试方法

TestAddRoleToUser

User user  =  session.Load( typeof  (User),  1 as  User;
Role role 
=  session.Load( typeof  (Role),  3 as  Role;

user.Roles.Add(role);
role.Users.Add(user);

session.Update(user);
session.Flush();

 TestRemoveRoleFromUser

User user  =  session.Load( typeof  (User),  1 as  User;
Role role 
=  session.Load( typeof  (Role),  2 as  Role;

user.Roles.Remove(role);
role.Users.Remove(user);

session.Update(user);
session.Flush();

 

 TestUpdateUserWithRole

User user  =  session.Load( typeof (User),  2 as  User;
((Role) user.Roles[
0 ]).RoleName  =   " UpdateRole " ;

session.Update(user);
session.Flush();

TestDeleteUserWithSetRole

User user  =  session.Load( typeof  (User),  1 as  User;
session.Delete(user);
session.Flush();

c.测试结果

测试方法

save-update

delete

delete-orphan

all

all-delete-orphan

none

TestAddRoleToUserYYYYYY
TestRemoveRoleFromUserYYYYYY
TestUpdateUserWithRoleYYYYYY
TestDeleteUserWithSetRoleNUer被删除,但和其有关的Role也被删除Uer被删除,但和其有关的Role也被删除Uer被删除,但和其有关的Role也被删除Uer被删除,但和其有关的Role也被删除N

 三、结论

关联是NHibernate里面功能很强的一块,但也使很容易滥用而造成引起性能或其他问题的地方。所以请慎重的使用。

在使用之前,请考虑好以下问题:

1.关系分析,一对多,多对多,还是一对一。

2.确定依赖关系,例如:Child依赖于Parent。

3.是否允许存在孤儿,例如:存在Child没有Parent(即在数据库中ParentId为Null的Child)。

4.在对等的关系中是否有主动端。例如:需要给Parent设置Child还是给Child找Parent,或者两边都可以操作。

5.关联两端可能出现的数据量以及在页面显示时是否分页。如果数据量大或者页面上需要分页显示,建议不要采用关联映射。如果数据量大,性能会不好,如果需要分页,关联所有数据似乎没有什么意思。

6.页面上可能的对象操作方法。例如:先读取一个Parent,然后添加Child,然后保存。

请根据你的情况设置关联映射,而对于cascade标准的设置可以满足绝大多数的需要,如一有特殊情况,请按照上面的分析选择合适的。

下载代码 

posted 

这篇关于NHibernate的关联映射(one-to-one,one-to-many,many-to-many)以及cascade分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/854023

相关文章

基于Go语言实现Base62编码的三种方式以及对比分析

《基于Go语言实现Base62编码的三种方式以及对比分析》Base62编码是一种在字符编码中使用62个字符的编码方式,在计算机科学中,,Go语言是一种静态类型、编译型语言,它由Google开发并开源,... 目录一、标准库现状与解决方案1. 标准库对比表2. 解决方案完整实现代码(含边界处理)二、关键实现细

PostgreSQL 序列(Sequence) 与 Oracle 序列对比差异分析

《PostgreSQL序列(Sequence)与Oracle序列对比差异分析》PostgreSQL和Oracle都提供了序列(Sequence)功能,但在实现细节和使用方式上存在一些重要差异,... 目录PostgreSQL 序列(Sequence) 与 oracle 序列对比一 基本语法对比1.1 创建序

MySQL复合查询从基础到多表关联与高级技巧全解析

《MySQL复合查询从基础到多表关联与高级技巧全解析》本文主要讲解了在MySQL中的复合查询,下面是关于本文章所需要数据的建表语句,感兴趣的朋友跟随小编一起看看吧... 目录前言:1.基本查询回顾:1.1.查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J1.2.按照部门

慢sql提前分析预警和动态sql替换-Mybatis-SQL

《慢sql提前分析预警和动态sql替换-Mybatis-SQL》为防止慢SQL问题而开发的MyBatis组件,该组件能够在开发、测试阶段自动分析SQL语句,并在出现慢SQL问题时通过Ducc配置实现动... 目录背景解决思路开源方案调研设计方案详细设计使用方法1、引入依赖jar包2、配置组件XML3、核心配

Java NoClassDefFoundError运行时错误分析解决

《JavaNoClassDefFoundError运行时错误分析解决》在Java开发中,NoClassDefFoundError是一种常见的运行时错误,它通常表明Java虚拟机在尝试加载一个类时未能... 目录前言一、问题分析二、报错原因三、解决思路检查类路径配置检查依赖库检查类文件调试类加载器问题四、常见

解决IDEA报错:编码GBK的不可映射字符问题

《解决IDEA报错:编码GBK的不可映射字符问题》:本文主要介绍解决IDEA报错:编码GBK的不可映射字符问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录IDEA报错:编码GBK的不可映射字符终端软件问题描述原因分析解决方案方法1:将命令改为方法2:右下jav

Python中的Walrus运算符分析示例详解

《Python中的Walrus运算符分析示例详解》Python中的Walrus运算符(:=)是Python3.8引入的一个新特性,允许在表达式中同时赋值和返回值,它的核心作用是减少重复计算,提升代码简... 目录1. 在循环中避免重复计算2. 在条件判断中同时赋值变量3. 在列表推导式或字典推导式中简化逻辑

Java程序进程起来了但是不打印日志的原因分析

《Java程序进程起来了但是不打印日志的原因分析》:本文主要介绍Java程序进程起来了但是不打印日志的原因分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java程序进程起来了但是不打印日志的原因1、日志配置问题2、日志文件权限问题3、日志文件路径问题4、程序

Java字符串操作技巧之语法、示例与应用场景分析

《Java字符串操作技巧之语法、示例与应用场景分析》在Java算法题和日常开发中,字符串处理是必备的核心技能,本文全面梳理Java中字符串的常用操作语法,结合代码示例、应用场景和避坑指南,可快速掌握字... 目录引言1. 基础操作1.1 创建字符串1.2 获取长度1.3 访问字符2. 字符串处理2.1 子字

SQL表间关联查询实例详解

《SQL表间关联查询实例详解》本文主要讲解SQL语句中常用的表间关联查询方式,包括:左连接(leftjoin)、右连接(rightjoin)、全连接(fulljoin)、内连接(innerjoin)、... 目录简介样例准备左外连接右外连接全外连接内连接交叉连接自然连接简介本文主要讲解SQL语句中常用的表