NHibernate关联讲解

代码
Many-To-Many 双向关联
1.双向N——N关联的两边都需要指定连接表的表名,外键列的列名。
2.两个set元素table必须指定,并且必须相同。
3.set元素的两个字元素:key和many-to-many都必须指定column属性,key和many-to-many分别制定本持久化类,关联类在连接表中的外键列名,因此两边的key与many-to-many的column属性交叉相同。
例如:
T_User表          T_User_Role        T_Role表
    Id     Int主键自增        UserId    User表id        Id    Int主键自增
   UserName     String 
50        RoleId    Role表id        RoleName    String 50
UserPassword     String 
50                        
User类:
―――――――――――――――――――――――――
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
namespace NHibernateTest.Model

    [Serializable]
    
public  class User
    {
        
private int _userid;

        
public virtual int UserId
        {
            
get { return _userid; }
            
set { _userid = value; }
        }
        
private string _username;

        
public virtual string UserName
        {
            
get { return _username; }
            
set { _username = value; }
        }
        
private string _userpassword;

        
public virtual string UserPassword
        {
            
get { return _userpassword; }
            
set { _userpassword = value; }
        }
        
private IList _roles;

        
public virtual IList Roles
        {
            
get { return _roles; }
            
set { _roles = value; }
        }
        
public User()
        {
            _userid 
= 0;
            _username 
= null;
            _userpassword 
= null;
            _roles 
= new ArrayList();

        }

    }
}

Role类:
―――――――――――――――――――――――
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
namespace NHibernateTest.Model
{
    [Serializable]
    
public class Role
    {
        
private int _roleid;

        
public virtual int RoleId
        {
            
get { return _roleid; }
            
set { _roleid = value; }
        }
        
private  string _rolename;

        
public virtual string RoleName
        {
            
get { return _rolename; }
            
set { _rolename = value; }
        }
        
private IList _users;

        
public virtual IList Users
        {
            
get { return _users; }
            
set { _users = value; }
        }
        
public Role()
        {
            _roleid 
= 0;
            _rolename 
=null;
            _users 
= new ArrayList();
        }

    }
}

User类映射文件User.hbm.xml:
-----------------------------------------------------------------------------
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="NHibernateTest.Model.User,NHibernateTest.Model"
table
="T_User">
    
<id name="UserId" column="Id" type="Int32" unsaved-value="0">
      
<generator class="native"/>
    
</id>
    
<property column="UserName" type="String" name="UserName" not-null="true" length="50" />
    
<property column="UserPassword" type="String" name="UserPassword" not-null="true" length="50" />
    
<bag name="Roles" table="T_User_Role" lazy="true">
     
<!--指定本持久化类(User)在连接表(T_User_Role)中的外键列名UserId,也就是T_User_Role表的UserId -->
<key column="UserId"/>
<!--指定关联类(Role)在连接表(T_User_Role)中的外键列名RoleId -->
          
<many-to-many class="NHibernateTest.Model.Role,NHibernateTest.Model" column="RoleId"/>
    
</bag>
  
</class>
</hibernate-mapping>

Role类映射文件 Role.hbm.xml:
---------------------------------------------------
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  
<class name="NHibernateTest.Model.Role,NHibernateTest.Model" table="T_Role">
    
<id name="RoleId" column="Id" type="Int32" unsaved-value="0">
      
<generator class="native"/>
    
</id>
    
<property column="RoleName" type="String" name="RoleName" not-null="true" length="50" />
    
<bag name="Users" table="T_User_Role" lazy="true" inverse="true">
      
<!--指定本持久化类(Role)在连接表(T_User_Role)中的外键列名,也就是T_User_Role表的RoleId-->
      
<key column="RoleId"/>
      
<!--指定关联类(User)在连接表(T_User_Role)中的外键列名-->
      
<many-to-many class="NHibernateTest.Model.User,NHibernateTest.Model" column="UserId"/>
    
</bag>
  
</class>
</hibernate-mapping>
实现代码如下:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using NHibernateTest.Model;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
namespace NHibernateTest
{
    
/*  many-to-many和别的关联映射有所不同。
     *  例子中:Role和User没有直接的依赖关系,而是通过一张中间表完成。
     *  在删除User时一般不会要求删除Role,而是删除之间的关系
     * (即从中间表删除数据)。
     
*/
public partial class Many_To_Many : System.Web.UI.Page
{
  
protected void Page_Load(object sender, EventArgs e)
{

}

protected void TestAddRoleToUser_Click(object sender, EventArgs e)
{
            Configuration config 
= new Configuration();
            config.AddAssembly(
"NHibernateTest.Model");
            ISessionFactory sessions 
= config.BuildSessionFactory();
            ISession session 
= sessions.OpenSession();
            ITransaction trans 
= session.BeginTransaction();
            
try
            {
                User user 
= session.Load(typeof(User), 4as User;
                Role role 
= session.Load(typeof(Role), 4as Role;
                user.Roles.Add(role);
                role.Users.Add(user);
                session.Update(user);
                trans.Commit();
            }
            
catch
            {
                trans.Rollback();
                
throw new Exception("失败!");
            }
            
finally
            {
                session.Close();
            }

}
//移除user和role的关联关系
protected void TestRemoveRoleFromUser_Click(object sender, EventArgs e)
{
            Configuration config 
= new Configuration();
            config.AddAssembly(
"NHibernateTest.Model");
            ISessionFactory sessions 
= config.BuildSessionFactory();
            ISession session 
= sessions.OpenSession();
            ITransaction trans 
= session.BeginTransaction();
            
try
            {
                
//移除user和role的关联关系
                User user = session.Load(typeof(User), 5as User;
                Role role 
= session.Load(typeof(Role), 5as Role;
                user.Roles.Remove(role);
                role.Users.Remove(user);
                session.Update(user);
                trans.Commit();
            }
            
catch
            {
                trans.Rollback();
                
throw new Exception("失败!");
            }
            
finally
            {
                session.Close();
            }

 }
//更新了与UserId=6关联的Role的RoleName名字
protected void TestUpdateUserWithRole_Click(object sender, EventArgs e)
 {
            Configuration config 
= new Configuration();
            config.AddAssembly(
"NHibernateTest.Model");
            ISessionFactory sessions 
= config.BuildSessionFactory();
            ISession session 
= sessions.OpenSession();
            ITransaction trans 
= session.BeginTransaction();
            
try
            {
                 
//更新了与UserId=6关联的Role的RoleName名字
                User user = session.Load(typeof(User), 6as User;
                ((Role)user.Roles[
0]).RoleName = "UpdateRole";
                session.Update(user);
                trans.Commit();
            }
            
catch
            {
                trans.Rollback();
                
throw new Exception("失败!");
            }
            
finally
            {
                session.Close();
            }

  }
   
//删除T_User表id=10的记录和删除了T_User_Role表的UserId=10的记录
   
//跟踪Sql:go
  /* DELETE FROM T_User_Role WHERE UserId = @p0', N'@p0 int', @p0 = 10
     DELETE FROM T_User WHERE Id = @p0', N'@p0 int', @p0 = 10
    
*/
protected void TestDeleteUserWithSetRole_Click(object sender, EventArgs e)
  {
            Configuration config 
= new Configuration();
            config.AddAssembly(
"NHibernateTest.Model");
            ISessionFactory sessions 
= config.BuildSessionFactory();
            ISession session 
= sessions.OpenSession();
            ITransaction trans 
= session.BeginTransaction();
            
try
            {
                User user 
= session.Load(typeof(User), 10as User;
                session.Delete(user);
                trans.Commit();
            }
            
catch
            {
                trans.Rollback();
                
throw new Exception("失败!");
            }
            
finally
            {
                session.Close();
            }

}
        
//添加了User,Role 以及User-Role的关系
protected void TestAddUserAndRole_Click(object sender, EventArgs e)
 {
            Configuration config 
= new Configuration();
            config.AddAssembly(
"NHibernateTest.Model");
            ISessionFactory sessions 
= config.BuildSessionFactory();
            ISession session 
= sessions.OpenSession();
            ITransaction trans 
= session.BeginTransaction();
            
try
            {
                User user 
= new User();
                user.UserName 
= "222";
                user.UserPassword 
= "222";   
                Role role 
= new Role();
                role.RoleName 
= "秘书"
                role.Users.Add(user);
                user.Roles.Add(role);
                session.Save(user);
                session.Save(role);
                trans.Commit();
            }
            
catch
            {
                trans.Rollback();
                
throw new Exception("失败!");
            }
            
finally
            {
                session.Close();
            }
        }
    }
}







One-To-Many(单项关联1-N)
因为集合属性都需要保存到另一个数据表中,所以保存集合属性表必须必须包含一个外键列,用于参照主键列。该外键列通过在
<Set/>等集合元素中使用<key…/>子元素column来映射。不管使用那种集合,使用<bag../>元素都将映射成无序集合。集合属性对应的表没有主键。
对于1—N的单向关联,需要在1的一端增加对应的集合映射元素。与映射集合类似,必须为
<set> ,<bag>等集合元素增加key子元素,用以映射关联外键列。
one
-to-many标签包含在标签bag/set中.bag标签的。inverse属性使collection不更新连接。
key标签的column属性指出了在另一个数据库表中加入外键,来关联本类。

T_Parent        T_Child
Id    Int主键自增        ChildId    Int自增
Name    String        Name    String 
            ParentId    T_Parent表Id

Many-To-One
many
-to-one:描述多对一的一种数据模型,它指定many一方是不能独立存在的,我个人认为many-to-one是NHB中保证数据有效性的最有用的一种映射,通过使用many-to-one能有效的防治孤儿记录被写入到数据表中。
<many-to-one
         name
="propertyName"(1)
          column
="column_name"(2)
          
class="ClassName"(3)
          cascade
="all|none|save-update|delete"(4)
         unique
="true|false" (10)
 
/>
.name:属性名。指出many一方的类用哪个属性和one一方的类关联.
.column:字段名(可选).指出many一方的类对应的数据表用哪个列和one一方的类对应的数据表关联(两表之间存在外键关联);
class:关联的类的名字(可选 - 默认是通过反射得到属性类型);
.cascade:指明哪些操作会从父对象级联到关联的对象(可选).cascade属性允许下列值:: all, save-update, delete, none. 设置除了none以外的其它值会传播特定的操作到关联的(子)对象中。
5.unique:允许产生外键列唯一约束的数据库定义语言(DDL)(可选)
原文地址:https://www.cnblogs.com/hubcarl/p/1706390.html