Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 275|回复: 0

[默认分类] NHibernate之旅(2):第一个NHibernate程序

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    发表于 2018-7-10 12:31:26 | 显示全部楼层 |阅读模式
    NHibernate之旅(2):第一个NHibernate程序
    本节内容

    开始使用NHibernate
    1.获取NHibernate
    2.建立数据库
    3.创建C#类库项目
    4.设计Domain
      
       4-1.设计持久化类
       4-2.编写映射文件
       
    5.数据访问层
      
       5-1.辅助类
       5-2.编写操作
       
    6.数据访问层的测试
      
       6-1.配置NHibernate
       6-2.测试
       
    结语

    作者注:2009-11-06已更新
    开始使用NHibernate
    我们亲自动手,一步一步搭建一个NHibernate程序来,我以一个实际场景电子交易程序来模拟,客户/订单/产品的经典组合。由于是第一次使用NHibernate,所以我们的目的是映射一张表并完成使用NHibernate来读取数据,下面的一幅图片给了我们第一印象。我们按照基本开发软件思想的流程一步一步完成。
    我使用的开发环境:Microsoft Visual Studio 2008 SP1、SQL Server 2008 Express、NHibernate 2.1.1GA。

    1.获取NHibernate
    使用官方2009年10月31日最新发布的NHibernate-2.1.1.GA版本。如果你第一次使用NHibernate,先到这里下载NHibernate最新版本(包括源码、发布版本、参考文档、API文档,可选择下载)。如果用到NHibernate的扩展项目到这里下载获得NHibernate Contrib最新版本。NHibernate-2.1.1.GA是.NET2.0平台的最后一个版本,关于NHibernate-2.1.1.GA的更多信息请点击这里
    关于NHibernate2.1版本的一些说明:
    NHibernate2.1版本改变了ByteCode延迟加载机制,有三种3种IoC框架动态代理方式,分别为:Castle框架、LinFu框架、Spring.Net框架。我们只要选择一种,在配置文件中配置proxyfactory.factory_class节点。
    如果使用Castle.DynamicProxy2动态代理,引用NHibernate.ByteCode.Castle.dll程序集并配置proxyfactory.factory_class节点为<property name="proxyfactory.factory_class"> NHibernate.ByteCode.Castle.ProxyFactoryFactory,NHibernate.ByteCode.Castle</property>
    如果使用LinFu.DynamicProxy动态代理,引用NHibernate.ByteCode.LinFu.dll程序集并配置proxyfactory.factory_class节点为<property name="proxyfactory.factory_class"> NHibernate.ByteCode.LinFu.ProxyFactoryFactory,NHibernate.ByteCode.LinFu</property>
    如果使用Spring.Aop动态代理,引用NHibernate.ByteCode.Spring.dll程序集并配置proxyfactory.factory_class节点为<property name="proxyfactory.factory_class"> NHibernate.ByteCode.Spring.ProxyFactoryFactory,NHibernate.ByteCode.Spring</property>
    另外NHibernate2.1要求.NET2.0 SP1以上版本 (System.DateTimeOffset),请使用VS2005的,务必打上Sp1补丁。推荐使用VS2008以上版本。
    2.建立数据库表
    由于第一次使用,还是按照我们传统的从数据库表配置吧。
    打开SQL Server Management Studio Express,新建一个新的数据库NHibernateSample,创建四个表:分别为客户表、订单表、订单产品表、产品表。

    3.创建C#类库项目
    由于是我们第一个程序,所以我没有按照Domain Driver Design方法去设计这个程序,按照大家的常规思想来实现的,以后有机会再介绍Domain Driver Design设计。

    注意为什么创建C#类库项目呢?在现在软件设计中,大多数都是采用多层架构来设计,
    比较经典的三层架构(页面表示层,业务逻辑层,数据访问层)通常而言业务逻辑层和数据访问层都是使用类库设计,页面表示层用Web应用程序设计,它引用业务逻辑层和数据访问层类库DLL程序集。

    使用VS2008创建C#类库的项目,命名为NHibernateSample。打开项目文件夹,在其项目文件目录上新建SharedLibs文件夹,把下载NHibernate相关程序集文件拷贝到SharedLibs文件夹下。如下图,这里我选择Castle框架动态代理:

    创建项目,结构如下:


    Domain(领域模型):用于持久化类和O/R Mapping操作
    Data(Data Access Layer数据访问层):定义对象的CRUD操作
    Data.Test(数据访问层测试):对数据访问层的测试,这里我使用Nunit单元测试框架
    Web:Web页面(这篇文章中暂未实现,请参考我的博客其他文章)


    项目引用

      Domain:引用Iesi.Collections.dll程序集(Set集合在这个程序集中)和Castle动态代理
      Data:引用NHibernate.dll和Iesi.Collections.dll程序集和动态代理相关程序集,Domain引用
      Data.Test:引用NHibernate.dll和Iesi.Collections.dll程序集,nunit.framework.dll程序集(测试框架),Domain和Data引用


    4.设计Domain
    4-1.编写持久化类
    按简单传统.NET对象(POCOs,Plain Old CLR Objects(Plain Ordinary CLR Objects))模型编程时需要持久化类。在NHibernate中,POCO通过.NET的属性机制存取数据,就可以把它映射成为数据库表。
    现在为Customer编写持久化类来映射成为数据库表。新建一个Customer.cs类文件:
    1. namespace NHibernateSample.Domain.Entities
    2. {
    3.     public class Customer
    4.     {
    5.         public virtual int Id { get; set; }
    6.         public virtual string FirstName { get; set; }
    7.         public virtual string LastName { get; set; }
    8.     }
    9. }
    复制代码

    规则

      NHibernate使用属性的getter和setter来实现持久化。
      属性可设置为public、internal、protected、protected internal或private



    注意NHibernate默认使用代理功能,要求持久化类不是sealed的,而且其公共方法、属性和事件声明为virtual。在这里,类中的字段要设置为virtual,否则出现“failed: NHibernate.InvalidProxyTypeException : The following types may not be used as proxies: NHibernateSample.Domain.Entities.Customer: method get_Id should be virtual,method set_Id should be virtual”异常。

    4-2.编写映射文件

    小提示我们要为Microsoft Visual Studio 2008添加编写NHibernate配置文件智能提示的功能。只要在下载的NHibernate里找到configuration.xsd和nhibernate-mapping.xsd两个文件并复制到X:\Program Files\Microsoft Visual Studio 9.0\Xml\Schemas目录即可。

    NHibernate要知道怎样去加载和存储持久化类的对象。这正是NHibernate映射文件发挥作用的地方。映射文件包含了对象/关系映射所需的元数据。元数据包含持久化类的声明和属性到数据库的映射。映射文件告诉NHibernate它应该访问数据库里面的哪个表及使用表里面的哪些字段。
    这里,我为Customer.cs类编写映射文件。新建一XML文件,命名为Customer.hbm.xml:
    1. <?xml version="1.0" encoding="utf-8" ?>
    2. <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
    3.    assembly="NHibernateSample.Domain"
    4. namespace="NHibernateSample.Domain.Entities">
    5.   
    6.   <class name ="Customer">
    7.     <id name="Id" column ="CustomerId">
    8.       <generator class ="native"/>
    9.     </id>
    10.     <property name ="FirstName"/>
    11.     <property name ="LastName"/>
    12.   </class>
    13. </hibernate-mapping>
    复制代码

    注意XML文件的默认生成操作为“内容”,这里需要修改为“嵌入的资源”生成,因为NHibernate是通过查找程序集中的资源文件映射实体,使用.NET Reflector查看程序集:




    否则出现“ failed: NHibernate.MappingException : No persister for: NHibernateSample.Domain.Entities.Customer”异常。

    5.编写数据访问层
    5-1.辅助类
    我们现在可以开始NHibernate了。首先,我们要从ISessionFactory中获取一个ISession(NHibernate的工作单元)。ISessionFactory可以创建并打开新的Session。一个Session代表一个单线程的单元操作。 ISessionFactory是线程安全的,很多线程可以同时访问它。ISession不是线程安全的,它代表与数据库之间的一次操作。ISession通过ISessionFactory打开,在所有的工作完成后,需要关闭。 ISessionFactory通常是个线程安全的全局对象,只需要被实例化一次。我们可以使用GoF23中的单例(Singleton)模式在程序中创建ISessionFactory。这个实例我编写了一个辅助类NHibernateHelper 用于创建ISessionFactory并配置ISessionFactory和打开一个新的Session单线程的方法,之后在每个数据操作类可以使用这个辅助类创建ISession 。
    1. public class NHibernateHelper
    2. {
    3.     private ISessionFactory _sessionFactory;
    4.     public NHibernateHelper()
    5.     {
    6.         _sessionFactory = GetSessionFactory();
    7.     }
    8.     private ISessionFactory GetSessionFactory()
    9.     {
    10.         return (new Configuration()).Configure().BuildSessionFactory();
    11.     }
    12.     public ISession GetSession()
    13.     {
    14.         return _sessionFactory.OpenSession();
    15.     }
    16. }
    复制代码
    5-2.编写操作
    在Data中新建一类NHibernateSample.cs,编写一方法GetCustomerId用于读取客户信息。在编写方法之前,我们需要初始化Session。
    1. protected ISession Session { get; set; }
    2. public NHibernateSample(ISession session)
    3. {
    4.     Session = session;
    5. }
    复制代码
    NHibernate有不同的方法来从数据库中取回对象。最灵活的方式是使用NHibernate查询语言(HQL),是完全基于面向对象的SQL。
    1. public void CreateCustomer(Customer customer)
    2. {
    3.     Session.Save(customer);
    4.     Session.Flush();
    5. }
    6. public Customer GetCustomerById(int customerId)
    7. {
    8.     return Session.Get<Customer>(customerId);
    9. }
    复制代码
    6.编写数据访问层的测试
    6-1.配置NHibernate
    我们可以几种方法来保存NHibernate的配置,具体以后来介绍,这里我们使用hibernate.cfg.xml文件来配置,不过不必担心,这个文件我们可以在src\NHibernate.Config.Templates文件夹下找到,直接复制到Data.Test中修改一下配置信息和文件输出属性就可以了。
    1. <?xml version="1.0" encoding="utf-8"?>
    2. <hibernate-configuration  xmlns="urn:nhibernate-configuration-2.2" >
    3.     <session-factory>
    4.         <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
    5.         <property name="connection.connection_string">
    6.             Data Source=.\SQLEXPRESS;Initial Catalog=NHibernateSample;
    7.       Integrated Security=True;Pooling=False
    8.         </property>
    9.         <property name="adonet.batch_size">10</property>
    10.         <property name="show_sql">true</property>
    11.         <property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
    12.         <property name="use_outer_join">true</property>
    13.         <property name="command_timeout">10</property>
    14.         <property name="query.substitutions">true 1, false 0, yes "Y", no "N"</property>
    15.      <property name="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory,
    16.       NHibernate.ByteCode.Castle</property>
    17.     <mapping assembly="NHibernateSample.Domain"/>   
    18.     </session-factory>
    19. </hibernate-configuration>
    复制代码

    注意XML文件的默认“复制到输出目录”为“不复制”,这里需要修改为“始终复制”。否则出现“failed: NHibernate.Cfg.HibernateConfigException : An exception occurred during configuration of persistence layer. ----> System.IO.FileNotFoundException : 未能找到文件“NHibernateSample\NHibernateSample.Data.Test\bin\Debug\hibernate.cfg.xml””异常。

    6-2.测试
    好了,终于可以使用我们的方法了,这里新建一个测试类NHibernateSampleFixture.cs来编写测试用例:调用NHibernateSample类中GetCustomerId方法查询数据库中CustomerId为1的客户,判断返回客户的Id是否为1。
    1. [TestFixture]
    2. public class NHibernateSampleFixture
    3. {
    4.     private NHibernateSample _sample;
    5.     [TestFixtureSetUp]
    6.     public void TestFixtureSetup()
    7.     {
    8.         _sample = new NHibernateSample();
    9.     }
    10.     [Test]
    11.     public void GetCustomerByIdTest()
    12.     {
    13.         var tempCutomer = new Customer {FirstName = "李", LastName = "永京"};
    14.         _sample.CreateCustomer(tempCutomer);
    15.         Customer customer = _sample.GetCustomerById(1);
    16.         int customerId = customer.Id;
    17.         Assert.AreEqual(1,customerId);
    18.     }
    19. }
    复制代码
    我们使用TestDriven.NET测试一下这个方法:OK,测试通过。这里我使用NHibernate监视器NHibernate Profiler查看结果:


    结语
    在这篇文章中,我们使用NHibernate来构建了一个最基本的项目,没有体现NHibernate更多细节,只描绘了NHibernate的基本面目。当然使用NHibernate有各种各样的程序架构,我按照一般模式构建的。请大家在实际项目中不要参考关于Session管理部分,本系列未做处理,更多实战知识以后介绍。

    NHibernate Q&A

      更多资料请点击NHibernate专题
      请到我的源代码库中下载源码。


    下次继续分享NHibernate!
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-3-29 17:15 , Processed in 0.364560 second(s), 48 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表