在NHibernate的映射中,关于继承的映射策略有3种方式

  • 单表继承
  • 类表继承
  • 具体表继承

  另外还有一种比较特别的多态映射

  • 隐式多态

  下面分别来阐述NHibernate继承映射的各种策略要点。

一、单表继承

  单表继承的方式是,所有的字段都放在一个表中,用一个字段来区分子类。使用配置节点<subclass>配置子类。

  看DEMO,首先新建一张Animal表如下:

  

  映射文件:Animal.hbm.xml:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Model.AnimalModel,Model" table="Animal" discriminator-value="动物">
<id name="AnimalId" column="AnimalId" type="Int32">
<generator class="native"/>
</id>
<discriminator column="AnimalType" type="String" />  <!-- 指定辨别字段列名,用于SQL语句筛选 -->
<property name="Name" column="Name" type="String"/>
<!--subclass放在这里也可以-->
<subclass extends="Model.AnimalModel, Model" name="Model.FrogModel, Model" discriminator-value="蛙"> //discriminator-value用来标记表中哪些行是青蛙
<property name="Foot" column="Foot" type="String"/>
</subclass>
</class>
</hibernate-mapping>

  映射文件:Fish.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false">
<subclass extends="Model.AnimalModel, Model" name="Model.FishModel, Model" discriminator-value="鱼">
<property name="Tail" column="Tail" type="String"/>
</subclass>
</hibernate-mapping>

  Model类:

namespace Model
{
public class AnimalModel
{
public virtual int AnimalId { get; set; }
public virtual string Name { get; set; }
}
public class FishModel : AnimalModel
{
public virtual string Tail { get; set; }
}
public class FrogModel : AnimalModel
{
public virtual string Foot { get; set; }
}
}

  执行操作:

        static void Main(string[] args)
{
ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();
using (ISession session = sessionFactory.OpenSession())
{
FishModel Fish = session.Get<FishModel>();
Console.WriteLine(Fish.AnimalId + " : " + Fish.Name + " : " + Fish.Tail); FrogModel Frog = session.Get<FrogModel>();
Console.WriteLine(Frog.AnimalId + " : " + Frog.Name + " : " + Frog.Foot);
}
Console.ReadKey();
}

  输出结果如下:

  

  我们看看SQL Server Profiler监控到执行的存储过程:

exec sp_executesql N'SELECT frogmodel0_.AnimalId as AnimalId0_0_, frogmodel0_.Name as Name0_0_, frogmodel0_.Foot as Foot0_0_ FROM Animal frogmodel0_ WHERE frogmodel0_.AnimalId=@p0 and frogmodel0_.AnimalType=''蛙''',N'@p0 int',@p0=2

  我们看到NHibernate,会利用我们设置的discriminator-value的值去过滤数据。使用单表继承,特别需要注意的就是,由子类定义的字段,不能有非空约束(not-null)。为什么?因为,如上面的Foot与Tail。青蛙则尾巴字段为空,鱼则肯定腿字段为空。

二、类表映射

  类表映射,故名思议就是一个子类一个表,其子类表通过外键关联到主表。然后一个子类对应一张表。配置节点为:<joined-subclass>

  首先我们将上面的表结构改为:

  

  映射文件的改动如下,Animal.hbm.xml:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Model.AnimalModel,Model" table="Animal"> <!--去掉discriminator-value,类表映射这个属性没用了-->
<id name="AnimalId" column="AnimalId" type="Int32">
<generator class="native"/>
</id>
<discriminator column="AnimalType" type="String" />
<property name="Name" column="Name" type="String"/>
<joined-subclass extends="Model.AnimalModel, Model" name="Model.FrogModel, Model" table="Frog"> <!--增加表名-->
<key column="Id"/> <!--添加主键Id-->
<property name="Foot" column="Foot" type="String"/>
</joined-subclass> <!--joined-subclass-->
</class>
</hibernate-mapping>

  Fish.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false">
<joined-subclass extends="Model.AnimalModel, Model" name="Model.FishModel, Model" table="Fish">
<key column="Id"/>
<property name="Tail" column="Tail" type="String"/>
</joined-subclass>
</hibernate-mapping>

  Program.cs不用改,输出结果也和上面一样,需要改变的仅仅是数据库表与映射文件。

  我们来看看SQL Server Profiler监控到执行了什么语句:

exec sp_executesql N'SELECT frogmodel0_.Id as AnimalId0_0_, frogmodel0_1_.Name as Name0_0_, frogmodel0_.Foot as Foot1_0_ FROM Frog frogmodel0_ inner join Animal frogmodel0_1_ on frogmodel0_.Id=frogmodel0_1_.AnimalId WHERE frogmodel0_.Id=@p0',N'@p0 int',@p0=2

  一个简单的inner join实现的。

  可以看到,使用这种方式的表比较多,关系模型实际是一对一关联。

类表映射使用Discriminator

  类表映射还可以加上个辨别字段,只是它除了用外键关联之外,还有个辨别字段。配置节点为<subclass><join>。

  现在,我们为上面的表结构再添加会一个辨别字段:

  

  映射文件Animal.hbm.xml:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Model.AnimalModel,Model" table="Animal" discriminator-value="动物"> <!--增加回辨别字段-->
<id name="AnimalId" column="AnimalId" type="Int32">
<generator class="native"/>
</id>
<discriminator column="Type" type="String" /> <!--指定辨别字段列名,会用在SQL语句-->
<property name="Name" column="Name" type="String"/>
<subclass extends="Model.AnimalModel, Model" name="Model.FrogModel, Model" discriminator-value="蛙"> <!--增加回辨别字段-->
<join table="Frog"> <!--增加join节点-->
<key column="Id"/>
<!--添加主键Id-->
<property name="Foot" column="Foot" type="String"/>
</join>
</subclass> <!--joined-subclass-->
</class>
</hibernate-mapping>

  Fish.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false">
<subclass extends="Model.AnimalModel, Model" name="Model.FishModel, Model" discriminator-value="鱼">
<join table="Fish">
<!--增加join节点-->
<key column="Id"/>
<property name="Tail" column="Tail" type="String"/>
</join>
</subclass>
</hibernate-mapping>

  Program.cs不变,输出结果不变。我们来看看生成的SQL语句:

exec sp_executesql N'SELECT frogmodel0_.AnimalId as AnimalId0_0_, frogmodel0_.Name as Name0_0_, frogmodel0_1_.Foot as Foot1_0_ FROM Animal frogmodel0_ inner join Frog frogmodel0_1_ on frogmodel0_.AnimalId=frogmodel0_1_.Id WHERE frogmodel0_.AnimalId=@p0 and frogmodel0_.Type=''蛙''',N'@p0 int',@p0=2

  另外,在映射文件里,可以混合使用单表映射与类表映射,例如

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Model.AnimalModel,Model" table="Animal" discriminator-value="动物"> <!--增加回辨别字段-->
<id name="AnimalId" column="AnimalId" type="Int32">
<generator class="native"/>
</id>
<discriminator column="Type" type="String" /> <!--指定辨别字段列名,会用在SQL语句-->
<property name="Name" column="Name" type="String"/>
<subclass extends="Model.AnimalModel, Model" name="Model.FishModel, Model" discriminator-value="鱼">  <!--单表映射-->
<join table="Fish">
<key column="Id"/>
<property name="Tail" column="Tail" type="String"/>
</join>
</subclass>
<joined-subclass extends="Model.AnimalModel, Model" name="Model.FrogModel, Model" table="Frog">  <!--类表映射-->
<key column="Id"/>
<property name="Foot" column="Foot" type="String"/>
</joined-subclass>
</class>
</hibernate-mapping>

三、具体表映射

  看了一下具体表映射的说明,决定不写了。这种方法实在太烂。不光表多,重复字段也多,我操。

  子类表中,每张表为对应类的所有属性(包括从超类继承的属性)定义相应字段。

  重复列太多,再加上每个类都一张表,第一范式都达不到吧。果断放弃。

四、隐式多态

  有一个缺点,无法生成有union的SQL语句。这还说什么,功能都不全。

NHibernate 继承映射(第十六篇)的更多相关文章

  1. Python之路【第十六篇】:Django【基础篇】

    Python之路[第十六篇]:Django[基础篇]   Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了O ...

  2. 跟我学SpringCloud | 第十六篇:微服务利剑之APM平台(二)Pinpoint

    目录 SpringCloud系列教程 | 第十六篇:微服务利剑之APM平台(二)Pinpoint 1. Pinpoint概述 2. Pinpoint主要特性 3. Pinpoint优势 4. Pinp ...

  3. 解剖SQLSERVER 第十六篇 OrcaMDF RawDatabase --MDF文件的瑞士军刀(译)

    解剖SQLSERVER 第十六篇 OrcaMDF RawDatabase --MDF文件的瑞士军刀(译) http://improve.dk/orcamdf-rawdatabase-a-swiss-a ...

  4. Egret入门学习日记 --- 第十六篇(书中 6.10~7.3节 内容)

    第十六篇(书中 6.10~7.3节 内容) 昨天搞定了6.9节,今天就从6.10节开始. 其实这个蛮简单的. 这是程序员模式. 这是设计师模式. 至此,6.10节 完毕. 开始 6.11节. 有点没营 ...

  5. Python自动化 【第十六篇】:JavaScript作用域和Dom收尾

    本节内容: javascript作用域 DOM收尾 JavaScript作用域 JavaScript的作用域一直以来是前端开发中比较难以理解的知识点,对于JavaScript的作用域主要记住几句话,走 ...

  6. NHibernate 集合映射基础(第四篇) - 一对一、 一对多、多对多小示例

    映射文件,用于告诉NHibernate数据库里的表.列于.Net程序中的类的关系.因此映射文件的配置非常重要. 一.一对一 NHibernate一对一关系的配置方式使用<one-to-one&g ...

  7. Struts2(十六篇)

    (一)Struts2框架概述 (二)Struts2配置文件 (三)Struts2的Action(简单讲解版) (四)Struts2的Action(深入讲解版) (五)Struts2处理结果管理 (六) ...

  8. NHibernate系列文章二十六:NHibernate查询之SQL Query查询(附程序下载)

    摘要 NHibernate在很早的版本就提供了SQL Query(原生SQL查询),对于很复杂的查询,如果使用其他的查询方式实现比较困难的时候,一般使用SQL Query.使用SQL Query是基于 ...

  9. Python之路(第二十六篇) 面向对象进阶:内置方法

    一.__getattribute__ object.__getattribute__(self, name) 无条件被调用,通过实例访问属性.如果class中定义了__getattr__(),则__g ...

随机推荐

  1. monkey测试===Android测试工具Monkey用法简介(转载)

    Monkey是Android中的一个命令行工具,可以运行在模拟器里或实际设备中.它向系统发送伪随机的用户事件流(如按键输入.触摸屏输入.手势输入等),实现对正在开发的应用程序进行压力测试.Monkey ...

  2. c json实战引擎五 , 优化重构

    引言 scjson是一个小巧的纯c跨平台小巧引擎. 适用于替换老的cJSON引擎的场景. 数据结构和代码布局做了大量改进.优势体现在以下几个方面: 1) 跨平台 (window 10 + VS2017 ...

  3. 如何掌握jQuery插件开发(高能)

    在实际开发工作中,总会碰到像滚动,分页,日历等展示效果的业务需求,对于接触过jQuery以及熟悉jQuery使用的人来说,首先想到的肯定是寻找现有的jQuery插件来满足相应的展示需求.目前页面中常用 ...

  4. 解决Mac开机变慢 command +option + P + R

    Mac开机变慢怎么办? command +option + P + R 重点是 开机 后 一直按 该4个键不放  听到3声音响 屏幕出现灰暗灰暗几次 开机速度 5s 重置PRAM和NVRAM的方法都是 ...

  5. python 字典value排序

    #!/usr/bin/env python#coding:utf-8s = {“a”:1,”b”:3,”c”:2} print sorted(s.iteritems(),key=lambda t:t[ ...

  6. Django 1.6在Windows平台下的配置

    Django 1.6 在Windows平台下的配置 前言 最近两天研究了下Django1.6在Windows平台中的配置安装,服务器采用Apache.期间遇到过许多新手所遇到的各种问题,也算是一种宝贵 ...

  7. BootStrap 实现导航栏nav透明,nav子元素文字不透明

    在给nav 的属性赋值 opacity:0.0透明度时会导致nav内子元素会继承opacity属性.此时再对子元素赋值opacity:1.0 时会导致 子元素实际opacity值为0.0*1.0=0. ...

  8. AC日记——大爷的字符串题 洛谷 P3709

    大爷的字符串题 思路: 莫队,需开O2,不开50: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 20000 ...

  9. BC-NFS部署报错节点间磁盘wwid冲突

    1.在部署公司的BC-NFS产品时,填好IP选好磁盘后,点击“创建”,就抛出如下提示: 2.关闭虚机,再打开虚机的控制台,点击磁盘,自定义serial number 3.启动虚机,再次登陆,查看磁盘w ...

  10. schtasks命令

    1.创建任务 在每天的22.44定时执行一次. schtasks /create /tn : 在特定时间运行一次. schtasks /create /tn : /sd // 2.运行一次任务 创建任 ...