`

O/R Mapping基础

阅读更多

对象和关系数据库之间的映射是用一个XML文档(XML document)来定义的。这个映射文档被设计为易读的,并且可以手工修改。映射语言是以.NET为中心的,意味着映射是按照持久化类的定义来创建的,而非表的定义。

请注意,虽然很多Hibernate用户选择手工定义XML映射文档,也有一些工具来生成映射文档,包括XDoclet,Middlegen和AndroMDA.

译者注:这里是NHibernate文档中一处没有从Hibernate文档中转换过来的部分,NHibernate中并没有像XDoclet,Middlegen和AndroMDA这样的工具,我一般会采用MyGeneration这样的代码生成工具来生成XML配置文档。

让我们从一个映射的例子开始:

<?xml version="1.0" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0"
namespace="Eg" assembly="Eg">
<class name="Cat" table="CATS" discriminator-value="C">
<id name="Id" column="uid" type="Int64">
<generator class="hilo"/>
</id>
<discriminator column="subclass" type="Char"/>
<property name="Birthdate" type="Date"/>
<property name="Color" not-null="true"/>
<property name="Sex" not-null="true" update="false"/>
<property name="Weight"/>
<many-to-one name="Mate" column="mate_id"/>
<set name="Kittens">
<key column="mother_id"/>
<one-to-many class="Cat"/>
</set>
<subclass name="DomesticCat" discriminator-value="D">
<property name="Name" type="String"/>
</subclass>
</class>
<class name="Dog">
<!-- mapping for Dog could go here -->
</class>
</hibernate-mapping>

我们现在开始讨论映射文档的内容。我们只描述NHibernate在运行时用到的文档元素和属性。映射文档还包括一些额外的可选属性和元素,它们在使用schema导出工具的时候会影响导出的数据库schema结果。(比如, not-null 属性。)

这个元素包括四个可选的属性。schema属性,指明了这个映射所引用的表所在的schema名称。假若指定了这个属性,表名会加上所指定的schema的名字扩展为全限定名。假若没有指定,表名就不会使用全限定名。default-cascade指定了未明确注明cascade属性的属性和集合类会采取什么样的默认级联风格。auto-import属性默认让我们在查询语言中可以使用非全限定名的类名。default-access告诉我们怎么访问属性值。

<hibernate-mapping
schema="schemaName" (1)
default-cascade="none|save-update" (2)
auto-import="true|false" (3)
default-access="property|field|nosetter|ClassName" (4)
assembly="assembly.name" (5)
namespace="namespace.name" (6)
> 
(1)

schema (可选): 数据库schema名称.

(2)

default-cascade (可选 - 默认为 none): 默认的级联风格.

(3)

auto-import (可选 - 默认为 true): 指定是否我们可以在查询语言中使用非全限定的类名(仅限于本映射文件中的类)。

(4)

default-access (可选 - 默认为 property): NHibernate访问属性值时的策略。

(5)

assembly (可选): 指定一个程序集,如果在映射文档中没有指定程序集,就使用这个程序集。

(6)

namespace (可选): 指定一个命名空间前缀,如果在映射文档中没有指定全限定名,就使用这个命名空间名。

假若你有两个持久化类,它们的非全限定名是一样的(就是在不同的命名空间里面--译者注),你应该设置auto-import="false"。假若说你把一个“import过”的名字同时对应两个类, NHibernate会抛出一个异常。

你可以使用class元素来定义一个持久化类:

<class
name="ClassName" (1)
table="tableName"(2)
discriminator-value="discriminator_value"(3)
mutable="true|false"(4)
schema="owner"(5)
proxy="ProxyInterface"(6)
dynamic-update="true|false"(7)
dynamic-insert="true|false"(8)
polymorphism="implicit|explicit"(9)
where="arbitrary sql where condition"(10)
persister="PersisterClass"(11)
lazy="true|false"(12)
/>
(1)

name: 持久化类(或者接口)的全限定名。

(2)

table: 对应的数据库表名。

(3)

discriminator-value (可选 - 默认和类名一样): 一个用于区分不同的子类的值,在多态行为时使用。

(4)

mutable (可选, 默认为 true): 表明该类的实例可变(不可变)。

(5)

schema (可选): 覆盖在根<hibernate-mapping> 元素中指定的schema名字。

(6)

proxy (可选): 指定一个接口,在延迟装载时作为代理使用。你可以在这里使用该类自己的名字。

(7)

dynamic-update (可选, 默认为 false): 指定用于UPDATE 的SQL将会在运行时动态生成,并且只更新那些改变过的字段。

(8)

dynamic-insert (可选, 默认为 false): 指定用于INSERT的 SQL 将会在运行时动态生成,并且只包含那些非空值字段。

(9)

polymorphism (可选, 默认为 implicit(隐式)): 界定是隐式还是显式的使用查询多态。

(10)

where (可选) 指定一个附加的SQL WHERE 条件,在抓取这个类的对象时会一直增加这个条件。

(11)

persister (可选): 指定一个定制的 IClassPersister.

(12)

lazy(可选):假若设置 lazy="true",就是设置这个类自己的名字作为proxy接口的一种等价快捷形式。

若指明的持久化类实际上是一个接口,也可以被完美地接受。其后你可以用 <subclass> 来指定该接口的实际实现类名。你可以持久化任何static(静态的)内部类。记得应该使用标准的类名格式,就是说比如:Eg.Foo+Bar

不可变类,mutable="false"不可以被应用程序更新或者删除。这可以让NHibernate做一些小小的性能优化。

可选的proxy属性可以允许延迟加载类的持久化实例。NHibernate开始会返回实现了这个命名接口或者子类(通过的Castle.DynamicProxy)。当代理的某个方法被实际调用的时候,真实的持久化对象才会被装载。参见下面的“用于延迟装载的代理”。

Implicit (隐式)的多态是指,如果查询中给出的是任何超类、该类实现的接口或者该类的名字,都会返回这个类的实例;如果查询中给出的是子类的名字,则会返回子类的实例。Explicit (显式)的多态是指,只有在查询中给出的明确是该类的名字时才会返回这个类的实例;同时只有当在这个 <class> 的定义中作为 <subclass> 或者 <joined-subclass> 出现的子类,才会可能返回。 大多数情况下,默认的polymorphism="implicit"都是合适的。 显式的多态在有两个不同的类映射到同一个表的时候很有用。(允许一个“轻型”的类,只包含部分表字段)。

persister属性可以让你定制这个类使用的持久化策略。你可以指定你自己实现的NHibernate.Persister.EntityPersister的子类,你甚至可以完全从头开始编写一个NHibernate.Persister.IClassPersister接口的实现,可能是用储存过程调用、序列化到文件或者LDAP数据库来实现的。参阅NHibernate.DomainModel.CustomPersister,这是一个简单的例子(“持久化”到一个Hashtable)。

请注意dynamic-updatedynamic-insert的设置并不会继承到子类,所以在<subclass>或者<joined-subclass>元素中可能需要再次设置。这些设置是否能够提高效率要视情形而定。请用你的智慧决定是否使用。

被映射的类必须声明对应数据库表主键字段。大多数类有一个属性,为每一个实例包含唯一的标识。 <id> 元素定义了该属性到数据库表主键字段的映射。

<id
name="propertyName" (1)
type="typename" (2)
column="column_name" (3)
unsaved-value="any|none|null|id_value" (4)
access="field|property|nosetter|ClassName"> (5)
<generator class="generatorClass"/>
</id>		
(1)

name (可选): 标识属性的名字。

(2)

type (可选): 标识NHibernate类型的名字。

(3)

column (可选 - 默认为属性名): 主键字段的名字。

(4)

unsaved-value (可选 - 默认为 null): 一个特定的标识属性值,用来标志该实例是刚刚创建的,尚未保存。这可以把这种实例和从以前的session中装载过(可能又做过修改--译者注)但未再次持久化的实例区分开来。

(5)

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

如果name属性不存在,会认为这个类没有标识属性。

unsaved-value 属性很重要!如果你的类的标识属性不是默认为null的,你应该指定正确的默认值。特别重要的是在使用值类型System.ValueType例如System.Int32 或者 System.Guid作为你的<id>属性时确保清楚的设置这个属性,因为System.ValueType对象不可能为null值。

还有一个另外的<composite-id>声明可以访问旧式的多主键数据。我们强烈不鼓励使用这种方式。

必须声明的 <generator> 子元素是一个.NET类的名字,用来为该持久化类的实例生成唯一的标识。如果这个生成器实例需要某些配置值或者初始化参数,用 <param>元素来传递。

<id name="Id" type="Int64" column="uid" unsaved-value="0">
<generator class="NHibernate.Id.TableHiLoGenerator">
<param name="table">uid_table</param>
<param name="column">next_hi_value_column</param>
</generator>
</id>

所有的生成器都实现NHibernate.Id.IdentifierGenerator接口。这是一个非常简单的接口;某些应用程序可以选择提供他们自己特定的实现。当然,NHibernate提供了很多内置的实现。下面是一些内置生成器的快捷名字:

identity

对DB2,MySQL, MS SQL Server, Sybase和HypersonicSQL的内置标识字段提供支持。返回的标识符是 Int64, Int32 或者 Int16类型的。

sequence(序列)

对DB2,MySQL, PostgreSQL, Oracle的内置标识字段提供支持。返回的标识符是Int64 Int32 或者 Int16类型的。

hilo(高低位)

使用一个高/低位算法来高效的生成Int64, Int32 或者 Int16类型的标识符。给定一个表和字段(默认分别是hibernate_unique_keynext)作为高位值得来源。高/低位算法生成的标识符只在一个特定的数据库中是唯一的。

seqhilo(使用序列的高低位)

使用一个高/低位算法来高效的生成Int64, Int32 或者 Int16类型的标识符,给定一个数据库序列(sequence)的名字。

uuid.hex

用一个System.Guid和它的ToString(string format)方法生成字符串类型的标识符。字符串的长度取决于 format的配置。

uuid.string

用一个新的System.Guid产生一个byte[] ,把它转换成字符串。

guid

用一个新的System.Guid 作为标识符。

guid.comb

用Jimmy Nilsson在文章http://www.informit.com/articles/article.asp?p=25862中描述的算法产生一个新的System.Guid

native(本地)

根据底层数据库的能力选择 identity, sequence 或者 hilo中的一个。

assigned(程序设置)

让应用程序在save()之前为对象分配一个标示符。

foreign(外部引用)

使用另外一个相关联的对象的标识符。和<one-to-one>联合一起使用。

 

<composite-id
name="propertyName"(1)
class="ClassName"(2)
unsaved-value="any|none"(3)
access="field|property|nosetter|ClassName">
<key-property name="propertyName" type="typename" column="column_name"/>
<key-many-to-one name="propertyName class="ClassName" column="column_name"/>
......
</composite-id>

如果表使用联合主键,你可以把类的多个属性组合成为标识符属性。<composite-id>元素接受<key-property>属性映射和<key-many-to-one>属性映射作为子元素。

<composite-id>
<key-property name="medicareNumber"/>
<key-property name="dependent"/>
</composite-id>

你的持久化类必须重载Equals()HashCode()方法,来实现组合的标识符判断等价.也必须实现Serializable接口

不幸的是,这种组合关键字的方法意味着一个持久化类是它自己的标识。除了对象自己之外,没有什么方便的“把手”可用。你必须自己初始化持久化类的实例,在使用组合关键字Load()持久化状态之前,必须填充他的联合属性。我们会在TODO:LINKTOCOMPENENTS中说明一种更加方便的方法,把联合标识实现为一个独立的类,下面描述的属性只对这种备用方法有效:

(1)

name (可选): 一个组件类型,持有联合标识(参见下一节)。

(2)

class (可选 - 默认为通过反射(reflection)得到的属性类型): 作为联合标识的组件类名(参见下一节)。

(3)

unsaved-value (可选 - 默认为 none): 假如被设置为any的值,就表示新创建,尚未被持久化的实例将持有的值。

在"一棵对象继承树对应一个表"的策略中,<discriminator>元素是必需的,它声明了表的识别器字段。识别器字段包含标志值,用于告知持久化层应该为某个特定的行创建哪一个子类的实例。只能使用如下受到限制的一些类型:String, Char, Int32, Byte, Int16, Boolean, YesNo, TrueFalse.

<discriminator
column="discriminator_column"(1)
type="discriminator_type"(2)
force="true|false"(3)
insert="true|false" (4)
/>
(1)

column (可选 - 默认为 class) 识别器字段的名字

(2)

type (可选 - 默认为 String) 一个NHibernate字段类型的名字

(3)

force (可选 - 默认为 false) "强制"NHibernate指定允许的识别器值,就算取得的所有实例都是根类的。

(4)

insert (可选 - 默认为 true) 当识别器是被映射的组件的标识符的一部分时设置为false

标识器字段的实际值是根据<class><subclass>元素的discriminator-value得来的.

force属性仅仅是在表包含一些未指定应该映射到哪个持久化类的时候才是有用的。这种情况不是经常会遇到。

元素<version>是可选的,表明表中包含附带版本信息的数据。这在你准备使用长事务(long transactions)的时候特别有用。(见后)

<version
column="version_column"(1)
name="propertyName"(2)
type="typename"(3)
access="field|property|nosetter|ClassName"(4)
unsaved-value="null|negative|undefined|value"(5)
/>
(1)

column (可选 - 默认为属性名): 指定持有版本号的字段名。

(2)

name: 持久化类的属性名。

(3)

type (可选 - 默认是 Int32): 版本号的类型。

(4)

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

(5)

unsaved-value (可选 - 默认是 undefined): 用于标明某个实例时刚刚被实例化的(尚未保存)版本属性值,依靠这个值就可以把这种情况和已经在先前的session中保存或装载的实例区分开来。(undefined指明使用标识属性值进行这种判断。)

版本号必须是以下类型: Int64, Int32, Int16, Ticks, Timestamp, 或者 TimeSpan.

可选的<timestamp>元素指明了表中包含时间戳数据。这用来作为版本的替代。时间戳本质上是一种对乐观锁定的一种不是特别安全的实现。当然,有时候应用程序可能在其他方面使用时间戳。

<timestamp
column="timestamp_column"(1)
name="propertyName"(2)
access="field|property|nosetter|ClassName"(3)
unsaved-value="null|negative|undefined|value"(4)
/>
(1)

column (可选 - 默认为属性名): 持有时间戳的字段名。

(2)

name: 在持久化类中的属性名,其类型是DateTime.

(3)

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

(4)

unsaved-value (可选 - 默认是 undefined): 用于标明某个实例时刚刚被实例化的(尚未保存)版本属性值,依靠这个值就可以把这种情况和已经在先前的session中保存或装载的实例区分开来。(undefined指明使用标识属性值进行这种判断。)

注意, <timestamp><version type="timestamp">是等价的。

<property> 元素为类声明了一个持久化的属性。

<property
name="propertyName"(1)
column="column_name"(2)
type="typename"(3)
update="true|false"(4)
insert="true|false"(5)
formula="arbitrary SQL expression"(6)
access="field|property|nosetter|ClassName"(7)
/>
(1)

name:属性的名字。

(2)

column (可选 - 默认为属性名字): 对应的数据库字段名。

(3)

type (可选): 一个NHibernate类型的名字。

(4)

update (可选 - 默认为 true) : 表明在用于UPDATE 的SQL语句中是否包含这个字段。

(5)

insert (可选 - 默认为 true) : 表明在用于INSERT的SQL语句中是否包含这个字段。这二者如果都设置为false则表明这是一个“外源性(derived)”的属性,它的值来源于映射到同一个(或多个)字段的某些其它属性,或者通过一个trigger(触发器),或者其它程序。

(6)

formula (可选): 一个SQL表达式,定义了这个计算(computed) 属性的值。计算属性没有和它对应的数据库字段。

(7)

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

typename可以是如下几种:

  1. NHibernate 基础类型之一 (比如: Int32, String, Char, DateTime, Timstamp, Single, Byte[], Object, ...).

  2. 基础类型的.NET类型名 (比如: System.Int16, System.Single, System.Char, System.String, System.DateTime, System.Byte[], ...).

  3. 枚举 System.Enum 名 (比如: Eg.Color).

  4. 一个可以序列化的 .NET 类的名字。

  5. 一个自定义类型的类的名字。(比如:Illflow.Type.MyCustomType, Illflow).

如果你没有指定类型,NHibernate会使用反射来得到这个名字的属性,以此来猜测正确的NHibernate类型。NHibernate会对属性读取器(getter访问器)的返回类进行解释,按照规则2,3,4的顺序。然而,这并不足够。 在某些情况下你仍然需要type属性。(比如,为了区别NHibernate.DateTimeNHibernate.Timestamp,或者为了指定一个自定义类型。)

access属性用来让你控制NHibernate如何在运行时访问属性。access的值属性应该用 access-strategy.naming-strategy的格式。.naming-stragey通常不需要设置。

 

 

 

转下文----》
评论

相关推荐

    hibernate2ch_reference.pdf

    1. **O/R Mapping基础** O/R Mapping是将对象模型与关系数据模型进行映射的技术,它允许程序员以面向对象的方式处理数据库。Hibernate通过XML或注解方式定义映射规则,实现了对象与数据库表之间的透明交互。 2. **...

    O/RM自动生成工具

    2. **O/R Mapping**:对象关系映射,是ORM的核心概念。它通过定义规则将数据库表映射为类,表中的字段映射为类的属性,从而实现对象与数据库记录的对应。这样,开发者可以直接操作对象,而无需关心底层SQL语句的编写...

    hibernate学习笔记

    Hibernate是Java领域中一款流行的持久化框架,它实现了对象关系映射(O/R Mapping),将复杂的数据库操作转化为对Java对象的操作,从而简化了开发过程。本文主要围绕Hibernate 3.2的学习笔记,涵盖其基本概念、配置...

    HIBERNATE入门

    【HIBERNATE入门】是针对Java开发者的培训资料,主要介绍了如何入门并掌握Hibernate这一流行的O/R Mapping框架。Hibernate是一种用于简化Java应用程序与数据库交互的开源库,它通过对象关系映射(O/R Mapping)技术...

    AutoJava Java代码自动生成工具

    AutoJava根据O/R Mapping规则生成表对应的Java对象,并且生成了所有的添加、删除、修改、查询等底层数据库操作代码。借助于AutoJava我们基本上不用再写与数据库相关的操作代码,只需要在此基础上实现相关的业务逻辑...

    Hibernate3 学习笔记.ppt

    【一、O/R Mapping】 O/R Mapping,即对象关系映射,是将对象模型与关系数据库之间进行映射的技术。在Hibernate中,O/R Mapping允许开发者以面向对象的方式来操作数据库,而无需关心底层的SQL语句。这极大地提高了...

    hibernate培训ppt

    总结,这份hibernate培训ppt提供了一个基础的Hibernate学习框架,帮助开发者理解O/R Mapping的核心概念,并学会如何利用Hibernate进行实际的数据库操作。虽然可能在深度上有所欠缺,但对于初学者而言,它是一个良好...

    Hibernate快速学习PPT

    【Hibernate快速学习PPT】是针对Java开发人员的一份教程资料,主要讲解了对象关系映射(Object/Relationship Mapping,简称O/R Mapping)框架Hibernate的核心概念和应用。这份PPT由加拿大嘉木华公司(JetGuo)提供,...

    hibernat培训.ppt[评价可免费]

    Hibernate作为优秀的O/R Mapping框架,具有开源、成熟、广泛使用等优点,且被JBoss选为实现Entity Beans的基础。使用Hibernate开发时,主要包括三个步骤:设计持久化类、建立类与数据库的映射,以及开发应用程序。...

    SQL2JAVA

    《SQL2JAVA:深入理解O/R Mapping工具》 在当今的软件开发中,尤其是在企业级应用领域,数据库管理和数据操作是至关重要的环节。SQL2JAVA作为一个O/R Mapping(对象关系映射)工具,旨在简化数据库与Java应用程序...

    hibernate培训教程

    本教程旨在帮助学员深入理解O/R Mapping原理,专注于流行的Java持久化框架Hibernate。学习此教程前,建议学员具备Java、SQL、JDBC的基础知识,以及面向对象开发的经验。通过培训,学员应能了解Hibernate的架构,掌握...

    马士兵hibernate学习笔记(原版)

    1. **O/R Mapping**:Object-Relational Mapping,对象关系映射,是将数据库中的关系数据模型映射到面向对象的编程语言中的一种技术。通过O/R Mapping,开发者可以避免直接编写SQL语句,而是以对象的形式处理数据,...

    EntityFramework6.1.3源码

    ADO.NET Entity Framework 是微软以 ADO.NET 为基础所发展出来的对象关系对应 (O/R Mapping) 解决方案,早期被称为 ObjectSpace,现已经包含在 Visual Studio 2008 Service Pack 1 以及 .NET Framework 3.5 Service ...

    hibernat培训教程,基础教程

    Hibernate是一种强大的Object-Relational Mapping(O/R Mapping)工具,它允许开发者将Java对象与关系数据库中的表进行映射,从而简化数据库操作。 **一、持久化层—O/R Mapping** 在基于B/S的三层架构中,业务...

    hibernat培训.ppt

    本培训材料主要针对Hibernate这一流行的Java对象关系映射(ORM)框架,旨在帮助已经熟悉Java、SQL和JDBC的开发者深入理解O/R Mapping原理,掌握Hibernate的使用,以便在实际项目开发中有效地利用Hibernate进行持久化...

Global site tag (gtag.js) - Google Analytics