十二、组件(component), 动态组件(dynamic-component)

  <component>元素把子对象的一些元素与父类对应的表的一些字段映射起来。 然后组件可以定义它们自己的属性、组件或者集合。

<component 
        name="PropertyName"                               (1)
        class="ClassName"                                  (2)
        insert="true|false"                                (3)
        upate="true|false"                                 (4)
        access="field|property|nosetter|ClassName"         (5)
        optimistic-lock="true|false"                       (6)
>
        <property ...../>
        <many-to-one .... />
        ........
</component>

 

 

 说明:
(1)

name: 属性名

(2)

class (可选 - 默认为通过反射得到的属性类型):组件(子)类的名字。

(3)

insert: 被映射的字段是否出现在SQL的INSERT语句中?

(4)

update: 被映射的字段是否出现在SQL的UPDATE语句中?

(5)

access可选 - 默认是 property): NHibernate用来访问属性的策略。

(6)

optimistic-lock (可选 - 默认是 true):表明更新此组件是否需要获取乐观锁。换句话说,当这个属性变脏时,是否增加版本号(Version

  其<property>子标签为子类的一些属性与表字段之间建立映射。

  <component>元素允许加入一个 <parent>子元素,在组件类内部就可以有一个指向其容器的实体的反向引用。

  <dynamic-component>元素允许把一个 IDictionaryp映射为组件,其属性名对应键值。 参见第 8.5 节 “动态组件 (Dynamic components)”.

十三、子类(subclass)
   最后,多态持久化需要为父类的每个子类都进行定义。 对于“每一棵类继承树对应一个表”的策略来说,就需要使用<subclass>定义。
<subclass
        name="ClassName"                              (1)
        discriminator-value="discriminator_value"     (2)
        proxy="ProxyInterface"                        (3)
        lazy="true|false"                             (4)
        dynamic-update="true|false"
        dynamic-insert="true|false">

        <property .... />
        .....
</subclass>
 说明:
(1)

name: 子类的全限定名。

(2)

discriminator-value (辨别标志) (可选 - 默认为类名):一个用于区分每个独立的子类的值。

(3)

proxy(代理) (可选): 指定一个类或者接口,在延迟装载时作为代理使用。

(4)

lazy(可选, 默认是true): 设置为 lazy="false" 禁止使用延迟抓取。

  每个子类都应该定义它自己的持久化属性和子类。 <version> 和<id>属性可以从根父类继承下来。 在一棵继承树上的每个子类都必须定义一个唯一的discriminator-value。如果没有指定,就会使用.NET类的全限定名。

十四、连接的子类(joined-subclass)
   此外,每个子类可能被映射到他自己的表中(每个子类一个表的策略)。被继承的状态通过和超类的表关联得到。我们使用<joined-subclass>元素。
<joined-subclass
        name="ClassName"                    (1)
        proxy="ProxyInterface"              (2)
        lazy="true|false"                   (3)
        dynamic-update="true|false"
        dynamic-insert="true|false">

        <key .... >

        <property .... />
        .....
</joined-subclass>

 

 

  说明:
(1)

name: 子类的全限定名。

(2)

proxy (可选): 指定一个类或者接口,在延迟装载时作为代理使用。

(3)

lazy(可选, 默认是 true): 设置为 lazy="false" 禁止使用延迟装载。 等价于设置proxy为自身类。

  这种映射策略不需要指定辨别标志(discriminator)字段。但是,每一个子类都必须使用 <key>元素指定一个表字段来持有对象的标识符。本章开始的映射可以被用如下方式重写:

 

<?xml version="1.0"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Eg"
    namespace="Eg">

        <class name="Cat" table="CATS">
                <id name="Id" column="uid" type="Int64">
                        <generator class="hilo"/>
                </id>
                <property name="BirthDate" type="Date"/>
                <property name="Color" not-null="true"/>
                <property name="Sex" not-null="true"/>
                <property name="Weight"/>
                <many-to-one name="Mate"/>
                <set name="Kittens">
                        <key column="MOTHER"/>
                        <one-to-many class="Cat"/>
                </set>
                <joined-subclass name="DomesticCat" table="DOMESTIC_CATS">
                    <key column="CAT"/>
                        <property name="Name" type="String"/>
                </joined-subclass>
        </class>

        <class name="Dog">
                <!-- mapping for Dog could go here -->
        </class>

</hibernate-mapping>

 

 

十五、联合子类(union-subclass)
   第三种选择是仅仅映射类继承树中具体类部分到表中(每个具体类一张表的策略)。 其中,每张表定义了类的所有持久化状态,包括继承的状态。 在 NHibernate 中,并不需要完全显式地映射这样的继承树。 你可以简单地使用单独的<class>定义映射每个类。 然而,如果你想使用多态关联(例如,一个对类继承树中超类的关联),你需要使用<union-subclass>映射。

 

<union-subclass
        name="ClassName"                    (1)
        table="tablename"                   (2)
        proxy="ProxyInterface"              (3)
        lazy="true|false"                   (4)
        dynamic-update="true|false"
        dynamic-insert="true|false"
        schema="schema"
        catalog="catalog"
        extends="SuperclassName"
        abstract="true|false"
        persister="ClassName"
        subselect="SQL expression"
        entity-name="EntityName"
        node="element-name">

        <property .... />
        .....
</union-subclass>

 

 

  说明:
(1)

name: 子类的全限定名。

(2)

table: 子类的表名

(3)

proxy (可选): 指定一个类或者接口,在延迟装载时作为代理使用。

(4)

lazy (可选, 默认是 true): 设置为 lazy="false" 禁止使用延迟装载。

这种映射策略不需要指定辨别标志(discriminator)字段。

 

十六、连接(join)
   使用 <join> 元素,可以将一个类的属性映射到多张表中。 当表之间存在一对一关系的时候使用。

 

<join
        table="tablename"                        (1)
        schema="owner"                           (2)
        fetch="join|select"                      (3)
        inverse="true|false"                     (4)
        optional="true|false">                   (5)

        <key ... />

        <property ... />
        ...
</join>

 

 

 说明:

(1)

table: 被连接表的名称。

(2)

schema (可选):覆盖由根<hibernate-mapping>元素指定的模式名称。

(3)

fetch (可选 - 默认是 join): 如果设置为默认值join, NHibernate 将使用一个内连接来得到这个类或其超类定义的join ,而使用一个外连接来得到其子类定义的join。如果设置为select, 则 NHibernate 将为子类定义的 join使用顺序选择。 这仅在一行数据表示一个子类的对象的时候才会发生。对这个类和其超类定义的join,依然会使用内连接得到。

(4)

inverse(可选 - 默认是 false): 如果打开,NHibernate 不会插入或者更新此连接定义的属性。

(5)

optional (可选 - 默认是 false): 如果打开,NHibernate 只会在此连接定义的属性非空时插入一行数据,并且总是使用一个外连接来得到这些属性。

  例如,一个人(person)的地址(address)信息可以被映射到单独的表中(并保留所有属性的值类型语义):

 

<class name="Person"
    table="PERSON">

    <id name="id" column="PERSON_ID">...</id>

    <join table="ADDRESS">
        <key column="ADDRESS_ID"/>
        <property name="address"/>
        <property name="zip"/>
        <property name="country"/>
    </join>

 

 此特性常常对遗留数据模型有用,我们推荐表个数比类个数少,以及细粒度的领域模型。然而,在单独的继承树上切换继承映射策略是有用的,后面会解释这点。

 

十七、引用

  假设你的应用程序有两个同样名字的持久化类,但是你不想在Hibernate查询中使用他们的全限定名。 除了依赖auto-import="true"以外,类也可以被显式地“import(引用)”。你甚至可以引用没有明确被映射的类和接口。

<import class="System.Object" rename="Universe"/>
<import
        class="ClassName"              (1)
        rename="ShortName"             (2)
/>

 

 

  说明:

(1)

class: 任何.NET类的全限定名。包括应用程序集名

(2)

rename(可选 - 默认为类的全限定名): 在查询语句中可以使用的名字。  

十八、实体(Entities)和值(values)
   为了理解很多与持久化服务相关的.NET语言级对象的行为,我们需要把它们分为两类:

  实体entity独立于任何持有实体引用的对象。与通常的.Net模型相比, 不再被引用的对象会被当作垃圾收集掉。实体必须被显式的保存和删除(除非保存和删除是从父实体向子实体引发的级联)。 这和ODMG模型中关于对象通过可触及保持持久性有一些不同——比较起来更加接近应用程序对象通常在一个大系统中的使用方法。 实体支持循环引用和交叉引用,它们也可以加上版本信息。

  一个实体的持久状态包含指向其他实体和值类型实例的引用。值可以是原始类型,集合(不是集合中的对象), 组件或者特定的不可变对象。与实体不同,值(特别是集合和组件)是通过可触及性来进行持久化和删除的。 因为值对象(和原始类型数据)是随着包含他们的实体而被持久化和删除的,他们不能被独立的加上版本信息。 值没有独立的标识,所以他们不能被两个实体或者集合共享。

  所有的NHibernate类型(如果.NET可空)除了集合类都支持null语义(继承System.ValueType)。

  直到现在,我们都一直使用术语“持久类”(persistent class)来代表实体。我们仍然会这么做。 然而严格说来,不是所有的用户自定义的,带有持久化状态的类都是实体。组件就是用户自定义类,却是值语义的。

十九、基本值类型
   基本值类型大致可以分为3类:System.ValueType类型, System.Object类型,System.Object大对象类型,像.Net的类型一样, System.ValueType类型不能存储null值,而System.Object类型可以。

表 5.3. System.ValueType映射类型

NHibernate类型 .NET类型 Database类型 备注
AnsiChar System.Char DbType.AnsiStringFixedLength - 1 char  
Boolean System.Boolean DbType.Boolean 在没有指定类型(type) 属性时的默认值。
Byte System.Byte DbType.Byte 在没有指定类型(type) 属性时的默认值。
Char System.Char DbType.StringFixedLength - 1 char 在没有指定类型(type) 属性时的默认值。
DateTime System.DateTime DbType.DateTime - ignores the milliseconds 在没有指定类型(type) 属性时的默认值。
Decimal System.Decimal DbType.Decimal 在没有指定类型(type) 属性时的默认值。
Double System.Double DbType.Double 在没有指定类型(type) 属性时的默认值。
Guid System.Guid DbType.Guid 在没有指定类型(type) 属性时的默认值。
Int16 System.Int16 DbType.Int16 在没有指定类型(type) 属性时的默认值。
Int32 System.Int32 DbType.Int32 在没有指定类型(type) 属性时的默认值。
Int64 System.Int64 DbType.Int64 在没有指定类型(type) 属性时的默认值。
PersistentEnum System.Enum 潜在类型对应的DbType 不用在映射文件指定type="PersistentEnum".而是提供枚举的程序集全名, 让NHibernate用反射来猜测类型。枚举使用的潜在类型决定适当的DbType.。
Single System.Single DbType.Single 在没有指定类型(type) 属性时的默认值。
Ticks System.DateTime DbType.Int64 type="Ticks"必须被指定。
TimeSpan System.TimeSpan DbType.Int64 在没有指定类型(type) 属性时的默认值。
Timestamp System.DateTime DbType.DateTime - 取决于数据库支持 type="Timestamp"必须被指定。
TrueFalse System.Boolean DbType.AnsiStringFixedLength- 一个字符,'Y' 或者'N' type="TrueFalse"必须被指定。
YesNo System.Boolean DbType.AnsiStringFixedLength- 一个字符,'Y' 或者'N' type="YesNo"必须被指定。

  

NHibernate Type .NET Type Database Type Remarks
AnsiString System.String DbType.AnsiString type="AnsiString"必须被指定。
CultureInfo System.Globalization.CultureInfo DbType.String - 表明文化(culture)的5个字符 在没有指定类型(type) 属性时的默认值。
Binary System.Byte[] DbType.Binary 在没有指定类型(type) 属性时的默认值。
Type System.Type DbType.String 保存应用程序集权限定名。 在没有指定类型(type) 属性时的默认值。
String System.String DbType.String 在没有指定类型(type) 属性时的默认值。

  

NHibernate Type .NET Type Database Type Remarks
StringClob System.String DbType.String type="StringClob"必须被指定。 整个字段在内存里可读。
BinaryBlob System.Byte[] DbType.Binary type="BinaryBlob"必须被指定。 整个字段在内存里可读。
Serializable Any System.Object 必须标注可序列化标签 DbType.Binary type="Serializable" 应该被指定. 如果不能为属性找到NHibernate类型,这是最后可依靠的类型。

  NHibernate为了兼容Hibernate也支持也一些额外的Java类型名(主要是方便能够使用Hibernate代码生成的映射文件), tt >type="integer"被映射为Int32 NHibernateType,type="short" 被映射为Int16 NHibernateType 。你可以通过查看NHibernate.Type.TypeFactory类的静态构造函数的代码查看到所有的上述所有的类型转换。