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),
4
)
as
User;
Role role
=
session.Load(
typeof
(Role),
4
)
as
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),
5
)
as
User;
Role role
=
session.Load(
typeof
(Role),
5
)
as
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),
6
)
as
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),
10
)
as
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
)
/>
1
.name:属性名。指出many一方的类用哪个属性和one一方的类关联.
2
.column:字段名(可选).指出many一方的类对应的数据表用哪个列和one一方的类对应的数据表关联(两表之间存在外键关联);
3
.
class
:关联的类的名字(可选
-
默认是通过反射得到属性类型);
4
.cascade:指明哪些操作会从父对象级联到关联的对象(可选).cascade属性允许下列值:: all, save
-
update, delete, none. 设置除了none以外的其它值会传播特定的操作到关联的(子)对象中。
5
.unique:允许产生外键列唯一约束的数据库定义语言(DDL)(可选)