NHibernate多对多关联映射的实现

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介:

上次用EF演示了数据库多对多关系的操作,这次我们还是引用上次的案例,来演示如何在C#当中使用NHibernate。

首先介绍一下NHibernate框架的来源。熟悉Java编程的读者肯定知道Hibernate这个ORM。NHibernate就来源于Java中著名的ORM框架—Hibernate,这点从名称当中就能够知道。目前NHibernate的最新版本是3.3.3,好像有一阵子没有update了,说明当前的版本也比较稳定了。具体的资料可以到官网查询:http://nhforge.org/

1、下载NHibernate

官网首页就有下载链接,直接下载就可以了。

下载好之后会得到一个zip包。

Center

我们就地解压可以看到如下目录和文件:

Center

我们重点关注以下目录的内容:

Configuration_Templates目录:默认提供的一些配置模板。有支持Oracle、Sql Server、MySQL等等。

Required_Bins目录:这里面存放了我们开发时常用的dll文件。其中的两个xsd文件是能够提供智能提示的文件,我们需要将它们俩复制到你本地的VS的Schemas目录下,比如我的目录为:D:\Program Files (x86)\Microsoft Visual Studio 11.0\Xml\Schemas 。

Center

复制好之后,重启VS,在我们写Hibernate配置文件时就有了智能提示了。

Center

准备工作做好之后,我们就可以正式演示。

2、创建一个类库项目Model

我们定义好两个类,分别为Student和Subject,为了便于管理,我们将它们放到Entity文件夹里,但命名空间仍为Model。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace  Model
{
     public  enum  Gender { Female, Male }
                                          
     public  class  Student
     {
         public  virtual  int ? StudentId {  get set ; }
         public  virtual  string  StudentName {  get set ; }
         public  virtual  Gender Gender {  get set ; }
         public  virtual  DateTime? BirthDay {  get set ; }
                                          
         public  virtual  IList<Subject> Subjects {  get set ; }
     }
}
1
2
3
4
5
6
7
8
9
10
namespace  Model
{
     public  class  Subject
     {
         public  virtual  int ? SubjectId {  get set ; }
         public  virtual  string  SubjectName {  get set ; }
                                        
         public  virtual  IList<Student> Students {  get set ; }
     }
}

这是一个典型的多对多的应用场景。一个学生可以选修多个课程,一个课程可以被多个学生选修。

接下来我们再创建相应的Hibernate配置文件(就是普通的xml文件,取名为Student.hbm.xml和Subject.hbm.xml)。

Student.hbm.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<? xml  version = "1.0"  encoding = "utf-8"  ?>
< hibernate-mapping  xmlns = "urn:nhibernate-mapping-2.2"  assembly = "Model"  namespace = "Model" >
   < class  name = "Student"  table = "T_Student"  lazy = "true" >
     < id  name = "StudentId"   type = "int"  column = "StudentId" >
       < generator  class = "native" />
     </ id >
     < property  name = "StudentName"  type = "string"  column = "StudentName" >
       < column  name = "StudentName"  length = "50" />
     </ property >
     < property  name = "Gender"  type = "Gender"  column = "Gender" >
       < column  name = "Gender"  length = "4" />
     </ property >
     < property  name = "BirthDay"  type = "datetime"  column = "BirthDay" >
       < column  name = "BirthDay"  length = "20" />
     </ property >
     < bag  name = "Subjects"  table = "T_Student_Subject" >
       < key  column = "StudentId" />
       < many-to-many  class = "Subject"  column = "SubjectId" />
     </ bag >
   </ class >
</ hibernate-mapping >

Subject.hbm.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<? xml  version = "1.0"  encoding = "utf-8"  ?>
< hibernate-mapping  xmlns = "urn:nhibernate-mapping-2.2"  assembly = "Model"  namespace = "Model" >
   < class  name = "Subject"  table = "T_Subject"  lazy = "true" >
     < id  name = "SubjectId"  type = "int"  column = "SubjectId" >
       < generator  class = "native" />
     </ id >
     < property  name = "SubjectName"  type = "string" >
       < column  name = "SubjectName"  length = "50" />
     </ property >
     < bag  name = "Students"  table = "T_Student_Subject" >
       < key  column = "SubjectId" />
       < many-to-many  class = "Student"  column = "StudentId" />
     </ bag >
   </ class >
</ hibernate-mapping >

便于管理我们同样的放到Config目录下(自己创建的文件夹)。


同时修改两个xml文件的生成操作由内容变为嵌入的资源(在vs中右键xml文件选择属性)

Center
3、创建一个控制台应用程序

表和实体对应的内容已经定义好,下面关键的就是要写代码来测试NHibernate了,本着尽量降低学习难度的原则,我这里就用控制台应用程序来验证(你也可以新建一个类库项目,然后用VS的单元测试或者第三方测试工具NUnit进行验证)。

首先将下载的开发包里面的Configuration_Templates文件夹下的MSSQL.cfg.xml复制到控制台应用程序中(为方便管理,我新建了一个Config文件夹,并把这个xml文件放到这里面,重命名为hibernate.cfg.xml)。

修改这个xml文件内容为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<? xml  version = "1.0"  encoding = "utf-8" ?>
<!--
This template was written to work with NHibernate.Test.
Copy the template to your NHibernate.Test project folder and rename it in hibernate.cfg.xml and change it
for your own use before compile tests in VisualStudio.
-->
<!-- This is the System.Data.dll provider for SQL Server -->
< hibernate-configuration   xmlns = "urn:nhibernate-configuration-2.2"  >
   < session-factory  name = "NHibernate.Test" >
     < property  name = "connection.driver_class" >NHibernate.Driver.SqlClientDriver</ property >
     < property  name = "connection.connection_string" >
       Server=.;database=nhibernateTest;uid=sa;pwd=123456;
     </ property >
     < property  name = "adonet.batch_size" >10</ property >
     < property  name = "show_sql" >true</ property >
     < property  name = "hbm2ddl.auto" >update</ property >
     < property  name = "dialect" >NHibernate.Dialect.MsSql2008Dialect</ property >
     < mapping  assembly = "Model" />
   </ session-factory >
</ hibernate-configuration >

注意这里面的一些节点的配置。比如mapping assembly里面的Model,就是指的是程序集的名称。同时将此文件的复制到输出目录方式修改为始终复制。

Center

接下来,给控制台项目添加两个dll的引用,分别为Iesi.Collections.dll和NHibernate.dll,也是在Required_Bins文件夹里面。

添加好引用,我们创建一个新的类NHibernateTest来写关键性代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
namespace  NHibernateDemo
{
     public  class  NHibernateTest
     {
         private  ISessionFactory _sessionFactory;
         public  ISessionFactory SessionFactory
         {
             get
             {
                 if  (_sessionFactory ==  null )
                 {
                     var  cfg =  new  NHibernate.Cfg.Configuration().Configure( "Config/hibernate.cfg.xml" );
                     _sessionFactory = cfg.BuildSessionFactory();
                 }
                 return  _sessionFactory;
             }
         }
                   
         public  void  TestInit()
         {
             using  (ISession session = SessionFactory.OpenSession())
             {
                 IList<Subject> subjects =  new  List<Subject>()
                 {
                      new  Subject { SubjectName =  "数学"  },
                      new  Subject { SubjectName =  "英语"  },
                      new  Subject { SubjectName =  "计算机"  },
                 };
                   
                 IList<Student> students =  new  List<Student>()
                 {
                     new  Student
                     {
                         StudentName =  "guwei4037" ,
                         Gender = Gender.Male,
                         BirthDay =  new  DateTime(1984, 11, 25),
                         Subjects = subjects.Where(x => x.SubjectName ==  "数学"  || x.SubjectName ==  "计算机" ).ToArray(),
                     },
                     new  Student
                     {
                         StudentName =  "gary.gu" ,
                         Gender = Gender.Female,
                         BirthDay =  new  DateTime(1987, 9, 15),
                         Subjects = subjects.Where(x => x.SubjectName ==  "数学"  || x.SubjectName ==  "英语" ).ToArray(),
                     },
                 };
                   
                 ITransaction tran = session.BeginTransaction();
                 try
                 {
                     foreach  ( var  subject  in  subjects)
                     {
                         session.Save(subject);
                     }
                   
                     foreach  ( var  student  in  students)
                     {
                         session.Save(student);
                     }
                   
                     tran.Commit();
                 }
                 catch  (Exception ex)
                 {
                     tran.Rollback();
                     throw  ex;
                 }
             }
         }
     }
}

这是一个带事务的多表插入的操作。

最后在Main方法中,写入简单的调用方法。

1
2
3
4
5
6
7
8
public  class  program
    {
        public  static  void  Main( string [] args)
        {
            NHibernateTest test =  new  NHibernateTest();
            test.TestInit();
        }
    }

在运行这个程序之前,还要做一件事,就是要在你的Sql Server中新建一个空的数据库nhibernateTest,否则会提示登录失败。

好了,这时我们已经准备好了一切,让我们运行一下这个控制台应用程序吧。

由于我们在hibernate.cfg.xml文件中定义了输入sql,所以会看到窗口中的内容。

Center

好,没有报错。我们打开Sql Server看一下最终的结果。

Center

而且数据库的表、主外键的关联以及数据都为我们自动生成了。

好,双向多对多的关系就演示到这里。如果需要更多详细的信息请参考:http://nhforge.org/doc/nh/en/index.html



本文转自 guwei4037  51CTO博客,原文链接:http://blog.51cto.com/csharper/1359457


相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS&nbsp;SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/sqlserver
相关文章
|
缓存 NoSQL Java
hibernate(三) 一对多映射关系
前面两节讲了hibernate的两个配置文件和hello world!。还有hibernate的一级缓存和三种状态,基本上hibernate就懂一点了,从这章起开始一个很重要的知识点,hibernate的关系映射。一对一、一对多、多对多的讲解。,希望你们能从中学到东西,我也从中巩固自己的知识
149 0
|
XML Java 数据库连接
Mybatis【一对多、多对一、多对多】知识要点
Mybatis【多表连接】 我们在学习Hibernate的时候,如果表涉及到两张的话,那么我们是在映射文件中使用..等标签将其的映射属性关联起来的...那么在我们Mybatis中又怎么做呢??? 先来回顾一下我们SQL99的语法: 一)内连接(等值连接):查询客户姓名,订单编号,订单价格 ...
1146 0
|
Java 关系型数据库 数据库连接
|
SQL Java 数据库连接
|
XML Java 数据库连接
Hibernate关联关系配置(一对多、一对一和多对多)
第一种关联关系:一对多(多对一) "一对多"是最普遍的映射关系,简单来讲就如消费者与订单的关系。 一对多:从消费者角的度来说一个消费者可以有多个订单,即为一对多。 多对一:从订单的角度来说多个订单可以对应一个消费者,即为多对一。   一对多关系在hbm文件中的配置信息: 消费者(一方): &lt;?xml version="1.0" encodin
1272 0