原文地址:http://jasondentler.com/blog/2009/08/how-to-using-the-n-stack-part-3/

Java – 一种代码松散的XML

在我们学习 Fluent NHibernate 之前, 应该先了解下老式的 NHibernate 映射文件应该是怎样写的。 在一个典型的 NHibernate 配置中,你会有很多类似这样的映射文件:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"><class name="NStackExample.Address, NStackExample.Core" table="Address"><composite-id><key-many-to-one name="Person" class="NStackExample.Person, NStackExample.Core" column="ID" /><key-property name="Type" type="Int32" /></composite-id><property name="City" type="String" length="255" /><property name="Lines" type="String" length="255" /><property name="State" type="String" length="2" /><property name="Zip" type="String" length="10" /></class>
</hibernate-mapping>

你必须为每一个实体类配置一个这样的映射文件,这种做法是从 Java 的 Hibernate 中遗留下来的。在我看来,这么做是非常痛苦的,不过幸运的是,有一个好办法来解决这个问题。

更好的选择: Fluent Mappings

有了 Fluent NHibernate ,上面的映射文件就可以用下面这个类来代替:

using FluentNHibernate.Mapping;namespace NStackExample.Data
{public class AddressMapping : ClassMap<Address>{public AddressMapping(){UseCompositeId().WithKeyReference(x => x.Person).WithKeyProperty(x => x.Type);Map(x => x.Lines).WithLengthOf(255);Map(x => x.City).WithLengthOf(255);Map(x => x.State).WithLengthOf(2);Map(x => x.Zip).WithLengthOf(5);}}
}

看起来这个类可能比之前的映射文件还要复杂,但是因为有智能感知,我们能轻而易举的完成,并且我们不用担心魔字符串(magic strings)的问题。当你使用重构工具来改变属性名称的时候,你的映射文件也会同步改变。

现在大家都知道基本的概念了吧,那么让我们继续。

Where?

因为数据库连接、 NHibernate 配置、实体类映射和 DAO 的实现只是我们选择的ORM的执行细节,所以应该把他们放到一个单独的程序集中。

  1. 创建一个新的类库项目,名字叫做:NStackExample.Data 。
  2. 添加新项目的引用,将 Core 项目,NHibernate.dll 和 FluentNHibernate.dll 添加进去。
  3. 为了以后我们能轻松的检索一些应用程序的设置,将System.Configuration.dll 也添加进去。
  4. 此外,在我们的 Web 项目中也需要将新建的项目添加到引用当中。

下面让我们来完成我们的映射文件。

using NStackExample;
using FluentNHibernate.Mapping;namespace NStackExample.Data
{public class CourseMapping : ClassMap<Course> {public CourseMapping(){Id(x => x.ID).GeneratedBy.GuidComb();Map(x => x.CourseNumber).Not.Nullable().WithLengthOf(4).UniqueKey("CourseNaturalKey");Map(x => x.Subject).Not.Nullable().WithLengthOf(4).UniqueKey("CourseNaturalKey");Map(x => x.Title).Not.Nullable().WithLengthOf(255);Map(x => x.Description).Not.Nullable().WithLengthOf(1024);Map(x => x.Hours).Not.Nullable();HasMany(x => x.Sections).AsSet().WithForeignKeyConstraintName("CourseSections");}}
}

上面的代码非常容易理解,最后得到的就是我们需要的映射文件。

我们的映射类继承自 ClassMap<Course> ,ClassMap 类是 Fluent NHibernate 搜索查找映射时的具体类型。在这里,这个类提供了 Course 实体类的映射。在构造函数中,我们定义了每个属性的具体映射。

  • 将 Id 设置成持久化对象标示符(POID),基本上这就是数据表的主键。对于有多个属性的主键,请参照我们上面 AddressMapping 示例中的 UseCompositeId 。我不建议使用多重主键,并且据我所知,Fluent NHibernate 也不支持多重主键。
  • GeneratedBy 是用来指定 POID 生成策略。在这里我们使用的是 GuidComb 。使用 GUID 做主键有非常多的好处,具体的内容大家可以参考 Davy Brion在NHForge博客上发表的随笔。
  • Map 只是将属性映射到数据库的列上。如果有需要的话,你可以指定 Not.Nullable 和 WithLengthOf 。
  • UniqueKey 指定了列的唯一索引。如果你对多个列指定了相同的名称,那么这些列都会变为这个唯一索引的一部分。在这个示例中,我们强制要求我们的自然键是唯一的。每个 subject 和 course number 都必须是唯一的。
  • HasMany 是定义了一个一对多的关系,你可以指定集合的确切行为。在这里有 Set 和 Bag 两个选项。
    • AsSet 不允许重复的项目
    • AsBag 允许重复的项目

默认情况下,所有关系都是延迟加载的。就是说当你从数据库中获取到了 course ,和其相关联的 sections 并不是马上获取出来,而是直到当你访问该属性的时候才会被加载进来,如果你从未访问过该属性的话,那么它永远都不会被加载,这样可以大大的提高性能。这些功能都是用代理来实现的。

下面容我们来映射 sections:

using NStackExample;
using FluentNHibernate.Mapping;namespace NStackExample.Data
{public class SectionMapping : ClassMap<Section> {public SectionMapping(){Id(x => x.ID).GeneratedBy.GuidComb();Map(x => x.FacultyName).WithLengthOf(255);Map(x => x.RoomNumber).WithLengthOf(10);Map(x => x.SectionNumber).WithLengthOf(4).Not.Nullable().UniqueKey("SectionNaturalKey");References(x => x.Course).Not.Nullable().UniqueKey("SectionNaturalKey");References(x => x.Term).Not.Nullable().UniqueKey("SectionNaturalKey");HasMany(x => x.StudentSections).AsSet().WithForeignKeyConstraintName("SectionStudentSections");}}
}

在这里引入了多对一关系的映射,可以把它看成一对多关系的另一边。 本示例中就是从孩子 section 到它的父亲 course 的关系。

练习:完成所有实体类的映射。

到这里或许你会在想这个系列是不是会很长很长呢?到现在我们甚至连数据库都还没有开始建立。不用担心,这些事 NHibernate 会帮我们做的。

8小时 or 8分钟?

在我没有使用 NHibernate 之前,我至少需要一天的时间来建立数据库。这让我很郁闷,估计大家也一样很不喜欢浪费这么多时间去建立数据库。不过,这样的事情将在今天结束。

声明: 如果你尝试使用现有的旧版数据库和数据库架构,没有什么调整的机会或者很渺茫,Fabio Maulo 的这篇随笔 将告诉你如何选择。

首先,让我们配置 NHibernate 。在 Fluent NHibernate Wiki 上 有一篇非常好的文章 介绍了应该如何配置。

using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
using System.IO;
using System.Configuration;namespace NStackExample.Data
{public class Configuration{private ISessionFactory m_Factory;private string m_SchemaPath;public Configuration Configure(){m_SchemaPath = ConfigurationManager.AppSettings["NStackExample.Data.Configuration.SchemaPath"];m_Factory = Fluently.Configure().Database(MsSqlConfiguration.MsSql2005.ConnectionString(x => x.FromConnectionStringWithKey("NStackExample.Data.Configuration.Db"))).Mappings(x => x.FluentMappings.AddFromAssemblyOf<CourseMapping>().ExportTo(m_SchemaPath)).ExposeConfiguration(BuildSchema).BuildSessionFactory();return this;}private void BuildSchema(NHibernate.Cfg.Configuration cfg){SchemaExport SchemaExporter = new SchemaExport(cfg);SchemaExporter.SetOutputFile(Path.Combine(m_SchemaPath, "schema.sql"));SchemaExporter.Create(true, false);}public ISession OpenSession(){if (m_Factory == null) Configure();return m_Factory.OpenSession();}}
}

配置分为两个部分:数据库和映射。在本示例中,数据库使用的是 SQL 2005,连接字符串是从 Web.config 文件中读取的。 所有的映射部分都是从
fluent 中读取的,没有自动映射。注意,我们出口的映射是在 web.config 文件的 appsettings 节中指定的一个目录,这会将我们 fluent 的映射分别转换成 hbm.xml文件。这么做是为了方便我们映射部分的调试,尤其是在需要 NHibernate 在线帮助的时候。

这里有个附加项,我们使用 ExposeConfiguration 方法调用 BuildSchema 函数来完成对 NHibernate 的配置。

在 BuildSchema 中,我们使用NHibernate中非常好的一个工具:schema export 。这个工具将会帮助我们创建数据库。构造函数接受两个布尔值的参数。第一个参数指定是否输出 DDL 文件 -- 一个包含所有表、键、索引和关系的数据库脚本。 第二个参数指定了是否将脚本应用到指定的数据库上。

非常简单吧。

两个警告:

  • 执行脚本将删除并创建和你的 Model 相关的每一个表,这对已有的环境可能是极具破坏性的操作。
  • 脚本一般不会带有“use [databasename]”语句,所以你如果不小心执行了,可能会建立到 master 数据库中,在执行脚本的时候请注意选择数据库。

在下篇教程当中,我们将介绍如何对你的映射进行测试,包括读取、查询和写入数据库。

转载于:https://www.cnblogs.com/LeoXing/archive/2009/10/05/how-to-using-the-n-stack-part-3.html

【翻译】How-To: Using the N* Stack, part 3相关推荐

  1. 【翻译】How-To: Using the N* Stack, part 5

    原文地址:Part 5: Fixing the Broken Stuff 到目前为止,我们一直都在关注 NHibernate 和持久化.在本篇中,我们会纠正之前模式和映射的问题来通过我们的测试.本篇结 ...

  2. C#5.0 In A NutShell翻译勘误

    一句话:这本书的翻译毁了这本书 简直就没有办法来形容这本书的翻译了.到处都是错误,而且是致命的错误.有些错误会对读者造成很严重的误导,这本书翻译的太不负责任了,翻译这本书的人都可以去死了,翻译完都没有 ...

  3. [源码]解析 SynchronousQueue 上界,下界.. 数据保存和数据传递. 堵塞队列. 有无频繁await?...

    简析SynchronousQueue.LinkedBlockingQueue(两个locker,更快),ArrayBlockingQueue(一个locker,读写都竞争) 三者都是blockingQ ...

  4. 了解MSIL汇编和IL汇编评估堆栈

    .assembly extern mscorlib {}.assembly Test{.ver 1:0:1:0}.module test.exe.method static void main() c ...

  5. essential-copying and pasting from Stack Overflow原文和翻译

    Introduction Inspired by this cover. The book is written in a deadpan manner. 根据封面的启发,这本书是在面无表情的方式下编 ...

  6. “Attention is All You Need 翻译

    <p><img src="output_0_0.png" alt="png"></p> "Attention is ...

  7. 基于PyTorch的Seq2Seq翻译模型详细注释介绍(一)

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/qysh123/article/deta ...

  8. 全文翻译(全文合集):TVM: An Automated End-to-End Optimizing Compiler for Deep Learning

    全文翻译(全文合集):TVM: An Automated End-to-End Optimizing Compiler for Deep Learning 摘要 人们越来越需要将机器学习应用到各种各样 ...

  9. 全文翻译(二): TVM: An Automated End-to-End Optimizing Compiler for Deep Learning

    全文翻译(二): TVM: An Automated End-to-End Optimizing Compiler for Deep Learning 3.优化计算图 计算图是在DL框架中表示程序的常 ...

最新文章

  1. 网站基于vs,复选框,单选款
  2. MySQL Proxy 安装与读写分离体验
  3. 平院Python习题
  4. qt调用mysql调用了存储过_Qt调用Server SQL中的存储过程
  5. Unix系统使用的地址索引结构有什么特点?
  6. 百度网盘就“用户激励计划”道歉;沈义人卸任 OPPO 全球营销总裁;Python 2.7.18 发布| 极客头条...
  7. advanced installer 使用常见问题整理
  8. 影响程序运行速度的几个因素
  9. 《sort命令的k选项大讨论》-linux命令五分钟系列之二十七
  10. html返回顶部函数,网页中返回顶部代码(多种方法)另附注释说明
  11. 客户分段模型(Customer Segmentation Models)
  12. Apktool反编译
  13. WPS的新建文档的体验
  14. 科大讯飞胡郁:我所领导的超脑项目,代表了AI的未来
  15. Oracle Temp临时表空间及其故障处理
  16. 12月份参加工作的年假怎么休_12月份满一年的,年假必须在12月份休完吗?
  17. CentOS系统安装
  18. 如何在VMware虚拟机上安装运行Mac OS系统(详细图文教程)
  19. Ubuntu下使用Requests 和 lxml抓取个人主页文章
  20. vc6.0静态链接库的创建与使用方法

热门文章

  1. iTerm2 快捷键
  2. es6 --- Promise.catch
  3. springCloud Finchley 实战入门(基于springBoot 2.0.3)【三 Eureka-高可用服务注册中心】...
  4. SANS研究所:7大最危险的攻击技术介绍
  5. 百年难得一见!阿里园区惊现双月争辉奇观!
  6. 《云计算:概念、技术与架构》一1.1 本书目标
  7. 如何修改myeclipse中web项目的工作路径或默认路径
  8. 如何在Django模板中注入全局变量
  9. IIS网站的权限设置问题
  10. JavaCL 1.0.0-RC3 发布,性能大幅提升