对象和关系数据库之间的映射通常是用一个XML文档(XML document)来定义的。这个映射文档被设计为易读的, 并且可以手工修改。映射语言是以Java为中心,这意味着映射文档是按照持久化类的定义来创建的, 而非表的定义。
请注意,虽然很多Hibernate用户选择手写XML映射文档,但也有一些工具可以用来生成映射文档, 包括XDoclet,Middlegen和AndroMDA。
让我们从一个映射的例子开始:
我们现在开始讨论映射文档的内容。我们只描述Hibernate在运行时用到的文档元素和属性。 映射文档还包括一些额外的可选属性和元素,它们在使用schema导出工具的时候会影响导出的数据库schema结果。 (比如, not-null 属性。)
所有的XML映射都需要定义如上所示的doctype。DTD可以从上述URL中获取, 从hibernate-x.x.x/src/net/sf/hibernate目录中、 或hibernate.jar文件中找到。Hibernate总是会首先在它的classptah中搜索DTD文件。 如果你发现它是通过连接Internet查找DTD文件,就对照你的classpath目录检查XML文件里的DTD声明。
这个元素包括一些可选的属性。schema和catalog属性, 指明了这个映射所连接(refer)的表所在的schema和/或catalog名称。 假若指定了这个属性,表名会加上所指定的schema和catalog的名字扩展为全限定名。假若没有指定,表名就不会使用全限定名。 default-cascade指定了未明确注明cascade属性的Java属性和 集合类Hibernate会采取什么样的默认级联风格。auto-import属性默认让我们在查询语言中可以使用 非全限定名的类名。
(1) catalog="catalogName" (2) default-cascade="cascade_style" (3) default-access="field|property|ClassName" (4) default-lazy="true|false" (5) auto-import="true|false" (6) package="package.name" (7) />
(1) | schema (可选): 数据库schema的名称。 |
(2) | catalog (可选): 数据库catalog的名称。 |
(3) | default-cascade (可选 - 默认为 none): 默认的级联风格。 |
(4) | default-access (可选 - 默认为 property): Hibernate用来访问属性的策略。可以通过实现PropertyAccessor接口 自定义。 |
(5) | default-lazy (可选 - 默认为 true): 指定了未明确注明lazy属性的Java属性和集合类, Hibernate会采取什么样的默认加载风格。 |
(6) | auto-import (可选 - 默认为 true): 指定我们是否可以在查询语言中使用非全限定的类名(仅限于本映射文件中的类)。 |
(7) | package (可选): 指定一个包前缀,如果在映射文档中没有指定全限定的类名, 就使用这个作为包名。 |
假若你有两个持久化类,它们的非全限定名是一样的(就是两个类的名字一样,所在的包不一样--译者注), 你应该设置auto-import="false"。假若说你把一个“import过”的名字同时对应两个类, Hibernate会抛出一个异常。
注意hibernate-mapping 元素允许你嵌套多个如上所示的
你可以使用class元素来定义一个持久化类:
(1) table="tableName" (2) discriminator-value="discriminator_value" (3) mutable="true|false" (4) schema="owner" (5) catalog="catalog" (6) proxy="ProxyInterface" (7) dynamic-update="true|false" (8) dynamic-insert="true|false" (9) select-before-update="true|false" (10) polymorphism="implicit|explicit" (11) where="arbitrary sql where condition" (12) persister="PersisterClass" (13) batch-size="N" (14) optimistic-lock="none|version|dirty|all" (15) lazy="true|false" (16) entity-name="EntityName" (17) check="arbitrary sql check condition" (18) rowid="rowid" (19) subselect="SQL expression" (20) abstract="true|false" (21) entity-name="EntityName" (22) node="element-name" (23) />
(1) | name (可选): 持久化类(或者接口)的Java全限定名。 如果这个属性不存在,Hibernate将假定这是一个非POJO的实体映射。 |
(2) | table (可选 - 默认是类的非全限定名): 对应的数据库表名。 |
(3) | discriminator-value (可选 - 默认和类名一样): 一个用于区分不同的子类的值,在多态行为时使用。它可以接受的值包括 null 和 not null。 |
(4) | mutable (可选,默认值为true): 表明该类的实例是可变的或者可变的。 |
(5) | schema (可选): 覆盖在根 |
(6) | catalog (可选): 覆盖在根 |
(7) | proxy (可选): 指定一个接口,在延迟装载时作为代理使用。 你可以在这里使用该类自己的名字。 |
(8) | dynamic-update (可选, 默认为 false): 指定用于UPDATE 的SQL将会在运行时动态生成,并且只更新那些改变过的字段。 |
(9) | dynamic-insert (可选, 默认为 false): 指定用于INSERT的 SQL 将会在运行时动态生成,并且只包含那些非空值字段。 |
(10) | select-before-update (可选, 默认为 false): 指定Hibernate除非确定对象真正被修改了(如果该值为true-译注),否则不会执行SQL UPDATE操作。在特定场合(实际上,它只在一个瞬时对象(transient object)关联到一个 新的session中时执行的update()中生效),这说明Hibernate会在UPDATE 之前执行一次额外的SQL SELECT操作,来决定是否应该执行 UPDATE。 |
(11) | polymorphism(多态) (可选, 默认值为 implicit (隐式) ): 界定是隐式还是显式的使用多态查询(这只在Hibernate的具体表继承策略中用到-译注)。 |
(12) | where (可选) 指定一个附加的SQLWHERE 条件, 在抓取这个类的对象时会一直增加这个条件。 |
(13) | persister (可选): 指定一个定制的ClassPersister。 |
(14) | batch-size (可选,默认是1) 指定一个用于 根据标识符(identifier)抓取实例时使用的"batch size"(批次抓取数量)。 |
(15) | optimistic-lock(乐观锁定) (可选,默认是version): 决定乐观锁定的策略。 |
(16) | lazy (optional): 通过设置lazy="false", 所有的延迟加载(Lazy fetching)功能将未被激活(disabled)。 |
(17) | entity-name (可选): Hibernate3允许一个类进行多次映射( 默认情况是映射到不同的表),并且允许使用Maps或XML代替Java层次的实体映射 (也就是实现动态领域模型,不用写持久化类-译注)。 更多信息请看第 5.4 节 “动态模型(Dynamic models)” and 第 19 章 XML映射。 |
(18) | check (可选): 这是一个SQL表达式, 用于为自动生成的schema添加多行(multi-row)约束检查。 |
(19) | rowid (可选): Hibernate可以使用数据库支持的所谓的ROWIDs,例如: Oracle数据库,如果你设置这个可选的rowid, Hibernate可以使用额外的字段rowid实现快速更新。ROWID是这个功能实现的重点, 它代表了一个存储元组(tuple)的物理位置。 |
(20) | subselect (可选): 它将一个不可变(immutable)并且只读的实体映射到一个数据库的 子查询中。它用于实现一个视图代替一张基本表,但是最好不要这样做。更多的介绍请看下面内容。 |
(21) | abstract (可选): 用于在 |
(22) | entity-name (可选, 默认为类名): 显式指定实体名 |
若指明的持久化类实际上是一个接口,这也是完全可以接受的。 之后你可以用
不可变类,mutable="false"不可以被应用程序更新或者删除。 这可以让Hibernate做一些小小的性能优化。
可选的proxy属性允许延迟加载类的持久化实例。 Hibernate开始会返回实现了这个命名接口的CGLIB代理。当代理的某个方法被实际调用的时候, 真实的持久化对象才会被装载。参见下面的“用于延迟装载的代理”。
Implicit (隐式)的多态是指,如果查询时给出的是任何超类、该类实现的接口或者该类的 名字,都会返回这个类的实例;如果查询中给出的是子类的名字,则会返回子类的实例。 Explicit (显式)的多态是指,只有在查询时给出明确的该类名字时才会返回这个类的实例; 同时只有在这个
persister属性可以让你定制这个类使用的持久化策略。 你可以指定你自己实现 org.hibernate.persister.EntityPersister的子类,你甚至可以完全从头开始编写一个 org.hibernate.persister.ClassPersister接口的实现, 比如是用储存过程调用、序列化到文件或者LDAP数据库来实现。 参阅org.hibernate.test.CustomPersister,这是一个简单的例子 (“持久化”到一个Hashtable)。
请注意dynamic-update和dynamic-insert的设置并不会继承到子类, 所以在
使用select-before-update通常会降低性能。如果你重新连接一个脱管(detache)对象实例 到一个Session中时,它可以防止数据库不必要的触发update。 这就很有用了。
如果你打开了dynamic-update,你可以选择几种乐观锁定的策略:
version(版本检查) 检查version/timestamp字段
all(全部) 检查全部字段
dirty(脏检查)只检察修改过的字段
none(不检查)不使用乐观锁定
我们非常强烈建议你在Hibernate中使用version/timestamp字段来进行乐观锁定。 对性能来说,这是最好的选择,并且这也是唯一能够处理在session外进行操作的策略(例如: 在使用Session.merge()的时候)。
对Hibernate映射来说视图和表是没有区别的,这是因为它们在数据层都是透明的( 注意:一些数据库不支持视图属性,特别是更新的时候)。有时你想使用视图,但却不能在数据库 中创建它(例如:在遗留的schema中)。这样的话,你可以映射一个不可变的(immutable)并且是 只读的实体到一个给定的SQL子查询表达式:
select item.name, max(bid.amount), count(*) from item join bid on bid.item_id = item.id group by item.name ...
定义这个实体用到的表为同步(synchronize),确保自动刷新(auto-flush)正确执行, 并且依赖原实体的查询不会返回过期数据。
被映射的类必须定义对应数据库表主键字段。大多数类有一个JavaBeans风格的属性, 为每一个实例包含唯一的标识。
(1) type="typename" (2) column="column_name" (3) unsaved-value="null|any|none|undefined|id_value" (4) access="field|property|ClassName" (5) node="element-name|@attribute-name|element/@attribute|.">
(1) | name (可选): 标识属性的名字。 |
(2) | type (可选): 标识Hibernate类型的名字。 |
(3) | column (可选 - 默认为属性名): 主键字段的名字。 |
(4) | unsaved-value (可选 - 默认为一个字段判断(sensible)的值): 一个特定的标识属性值,用来标志该实例是刚刚创建的,尚未保存。 这可以把这种实例和从以前的session中装载过(可能又做过修改--译者注) 但未再次持久化的实例区分开来。 |
(5) | access (可选 - 默认为property): Hibernate用来访问属性值的策略。 |
如果 name属性不存在,会认为这个类没有标识属性。
unsaved-value 属性很重要!如果你的类的标识属性不是默认为 正常的Java默认值(null或零),你应该指定正确的默认值。
还有一个另外的
可选的
uid_table next_hi_value_column
所有的生成器都实现net.sf.hibernate.id.IdentifierGenerator接口。 这是一个非常简单的接口;某些应用程序可以选择提供他们自己特定的实现。当然, Hibernate提供了很多内置的实现。下面是一些内置生成器的快捷名字:
用于为long, short或者int类型生成 唯一标识。只有在没有其他进程往同一张表中插入数据时才能使用。 在集群下不要使用。
对DB2,MySQL, MS SQL Server, Sybase和HypersonicSQL的内置标识字段提供支持。 返回的标识符是long, short 或者int类型的。
在DB2,PostgreSQL, Oracle, SAP DB, McKoi中使用序列(sequence), 而在Interbase中使用生成器(generator)。返回的标识符是long, short或者 int类型的。
使用一个高/低位算法高效的生成long, short 或者 int类型的标识符。给定一个表和字段(默认分别是是 hibernate_unique_key 和next_hi)作为高位值的来源。 高/低位算法生成的标识符只在一个特定的数据库中是唯一的。
使用一个高/低位算法来高效的生成long, short 或者 int类型的标识符,给定一个数据库序列(sequence)的名字。
用一个128-bit的UUID算法生成字符串类型的标识符, 这在一个网络中是唯一的(使用了IP地址)。UUID被编码为一个32位16进制数字的字符串。
在MS SQL Server 和 MySQL 中使用数据库生成的GUID字符串。
根据底层数据库的能力选择identity, sequence 或者hilo中的一个。
让应用程序在save()之前为对象分配一个标示符。这是
通过数据库触发器选择一些唯一主键的行并返回主键值来分配一个主键。
使用另外一个相关联的对象的标识符。通常和
hilo 和 seqhilo生成器给出了两种hi/lo算法的实现, 这是一种很令人满意的标识符生成算法。第一种实现需要一个“特殊”的数据库表来保存下一个可用的“hi”值。 第二种实现使用一个Oracle风格的序列(在被支持的情况下)。
hi_value next_value 100
hi_value 100
很不幸,你在为Hibernate自行提供Connection时无法使用hilo。 当Hibernate使用JTA获取应用服务器的数据源连接时,你必须正确地配置 hibernate.transaction.manager_lookup_class。
UUID包含:IP地址,JVM的启动时间(精确到1/4秒),系统时间和一个计数器值(在JVM中唯一)。 在Java代码中不可能获得MAC地址或者内存地址,所以这已经是我们在不使用JNI的前提下的能做的最好实现了。
对于内部支持标识字段的数据库(DB2,MySQL,Sybase,MS SQL),你可以使用identity关键字生成。 对于内部支持序列的数据库(DB2,Oracle, PostgreSQL, Interbase, McKoi,SAP DB), 你可以使用sequence风格的关键字生成。 这两种方式对于插入一个新的对象都需要两次SQL查询。
person_id_sequence
对于跨平台开发,native策略会从identity, sequence 和hilo中进行选择,选择哪一个,这取决于底层数据库的支持能力。
如果你需要应用程序分配一个标示符(而非Hibernate来生成),你可以使用assigned 生成器。这种特殊的生成器会使用已经分配给对象的标识符属性的标识符值。 这个生成器使用一个自然键(natural key,有商业意义的列-译注)作为主键,而不是使用一个代理键( surrogate key,没有商业意义的列-译注)。
当选择assigned生成器时,除非有一个version或timestamp属性,或者你定义了 Interceptor.isUnsaved(),否则需要让Hiberante使用 unsaved-value="undefined",强制Hibernatet查询数据库来确定一个实例是瞬时的(transient) 还是脱管的(detached)。
仅仅用于遗留的schema中 (Hibernate不能使用触发器生成DDL)。
socialSecurityNumber
在上面的例子中,类定义了一个命名为socialSecurityNumber的唯一值属性, 它是一个自然键(natural key),命名为person_id的代理键(surrogate key) 的值由触发器生成。
......
For a table with a composite key, you may map multiple properties of the class as identifier properties. The
如果表使用联合主键,你可以映射类的多个属性为标识符属性。
你的持久化类必须重载equals()和 hashCode()方法,来实现组合的标识符的相等判断。 实现Serializable接口也是必须的。
不幸的是,这种组合关键字的方法意味着一个持久化类是它自己的标识。除了对象自己之外, 没有什么方便的“把手”可用。你必须自己初始化持久化类的实例,在使用组合关键字load() 持久化状态之前,必须填充他的联合属性。我们会在第 9.4 节 “组件作为联合标识符(Components as composite identifiers)”章中说明一种 更加便捷的方法,把联合标识实现为一个独立的类,下面描述的属性只对这种备用方法有效:
name (可选):一个组件类型,持有复合标识(参见下一节)。
class (可选 - 默认为通过反射(reflection)得到的属性类型) : 作为联合标识的组件类名(参见下一节)。
unsaved-value (可选 - 默认为 undefined): 如果设置为any,就表示瞬时(transient)实例应该被重新初始化,或者如果 设置为none,则表示该实例是脱管对象。最好在所有的情况下都保持默认的值。
在"一棵对象继承树对应一个表"的策略中,
(1) type="discriminator_type" (2) force="true|false" (3) insert="true|false" (4) formula="arbitrary sql expression" (5) />
(1) | column (可选 - 默认为 class) 鉴别器字段的名字 |
(2) | type (可选 - 默认为 string) 一个Hibernate字段类型的名字 |
(3) | force(强制) (可选 - 默认为 false) "强制"Hibernate指定允许的鉴别器值,就算取得的所有实例都是根类的。 |
(4) | insert (可选 - 默认为true) 如果你的鉴别器字段也是映射为复合标识(composite identifier)的一部分,则需将 这个值设为false。(告诉Hibernate在做SQL INSERT 时不包含该列) |
(5) | formula (可选) 一个SQL表达式,在类型判断(判断是父类还是具体子类-译注)时执行。可用于基于内容的鉴别器。 |
鉴别器字段的实际值是根据
force属性仅仅是在表包含一些未指定应该映射到哪个持久化类的时候才是有用的。 这种情况不会经常遇到。
使用formula属性你可以定义一个SQL表达式,用来判断一个行数据的类型。
(1) name="propertyName" (2) type="typename" (3) access="field|property|ClassName" (4) unsaved-value="null|negative|undefined" (5) node="element-name|@attribute-name|element/@attribute|." />
(1) | column (可选 - 默认为属性名): 指定持有版本号的字段名。 |
(2) | name: 持久化类的属性名。 |
(3) | type (可选 - 默认是 integer): 版本号的类型。 |
(4) | access (可选 - 默认是 property): Hibernate用于访问属性值的策略。 |
(5) | unsaved-value (可选 - 默认是undefined): 用于标明某个实例时刚刚被实例化的(尚未保存)版本属性值,依靠这个值就可以把这种情况 和已经在先前的session中保存或装载的脱管(detached)实例区分开来。 (undefined指明使用标识属性值进行判断。) |
版本号必须是以下类型:long, integer, short, timestamp或者calendar。
一个脱管(detached)实例的version或timestamp不能为空(null),因为Hibernate不管 unsaved-value指定为何种策略,它将分离任何属性为空的version或timestamp 实例为瞬时(transient)实例。 避免Hibernate中的传递重附(transitive reattachment)问题的一个简单方法是 定义一个不能为空的version或timestamp属性,特别是在人们使用程序分配的标识符(assigned identifiers) 或复合主键时非常有用!
可选的
(1) name="propertyName" (2) access="field|property|ClassName" (3) unsaved-value="null|undefined" (4) node="element-name|@attribute-name|element/@attribute|." />
(1) | column (可选 - 默认为属性名): 持有时间戳的字段名。 |
(2) | name: 在持久化类中的JavaBeans风格的属性名, 其Java类型是 Date 或者 Timestamp的。 |
(3) | access (可选 - 默认是 property): Hibernate用于访问属性值的策略。 |
(4) | unsaved-value (可选 - 默认是null): 用于标明某个实例时刚刚被实例化的(尚未保存)版本属性值,依靠这个值就可以把这种情况和 已经在先前的session中保存或装载的脱管(detached)实例区分开来。(undefined 指明使用标识属性值进行这种判断。) |
注意,
(1) column="column_name" (2) type="typename" (3) update="true|false" (4) insert="true|false" (4) formula="arbitrary SQL expression" (5) access="field|property|ClassName" (6) lazy="true|false" (7) unique="true|false" (8) not-null="true|false" (9) optimistic-lock="true|false" (10) node="element-name|@attribute-name|element/@attribute|." />
(1) | name: 属性的名字,以小写字母开头。 |
(2) | column (可选 - 默认为属性名字): 对应的数据库字段名。 也可以通过嵌套的 |
(3) | type (可选): 一个Hibernate类型的名字。 |
(4) | update, insert (可选 - 默认为 true) : 表明用于UPDATE 和/或 INSERT 的SQL语句中是否包含这个被映射了的字段。这二者如果都设置为false 则表明这是一个“外源性(derived)”的属性,它的值来源于映射到同一个(或多个) 字段的某些其他属性,或者通过一个trigger(触发器)或其他程序。 |
(5) | formula (可选): 一个SQL表达式,定义了这个计算 (computed) 属性的值。计算属性没有和它对应的数据库字段。 |
(6) | access (可选 - 默认值为 property): Hibernate用来访问属性值的策略。 |
(7) | lazy (可选 - 默认为 false): 指定 指定实例变量第一次被访问时,这个属性是否延迟抓取(fetched lazily)( 需要运行时字节码增强)。 |
(8) | unique (可选): 使用DDL为该字段添加唯一的约束。 此外,这也可以用作property-ref的目标属性。 |
(9) | not-null (可选): 使用DDL为该字段添加可否为空(nullability)的约束。 |
(10) | optimistic-lock (可选 - 默认为 true): 指定这个属性在做更新时是否需要获得乐观锁定(optimistic lock)。 换句话说,它决定这个属性发生脏数据时版本(version)的值是否增长。 |
typename可以是如下几种:
Hibernate基础类型之一(比如:integer, string, character,date, timestamp, float, binary, serializable, object, blob)。
一个Java类的名字,这个类属于一种默认基础类型 (比如: int, float,char, java.lang.String, java.util.Date, java.lang.Integer, java.sql.Clob)。
一个可以序列化的Java类的名字。
一个自定义类型的类的名字。(比如: com.illflow.type.MyCustomType)。
如果你没有指定类型,Hibernarte会使用反射来得到这个名字的属性,以此来猜测正确的Hibernate类型。 Hibernate会按照规则2,3,4的顺序对属性读取器(getter方法)的返回类进行解释。然而,这还不够。 在某些情况下你仍然需要type属性。(比如,为了区别Hibernate.DATE 和Hibernate.TIMESTAMP,或者为了指定一个自定义类型。)
access属性用来让你控制Hibernate如何在运行时访问属性。在默认情况下, Hibernate会使用属性的get/set方法对(pair)。如果你指明access="field", Hibernate会忽略get/set方法对,直接使用反射来访问成员变量。你也可以指定你自己的策略, 这就需要你自己实现org.hibernate.property.PropertyAccessor接口, 再在access中设置你自定义策略类的名字。
衍生属性(derive propertie)是一个特别强大的特征。这些属性应该定义为只读,属性值在装载时计算生成。 你用一个SQL表达式生成计算的结果,它会在这个实例转载时翻译成一个SQL查询的SELECT 子查询语句。
注意,你可以使用实体自己的表,而不用为这个特别的列定义别名( 上面例子中的customerId)。同时注意,如果你不喜欢使用属性, 你可以使用嵌套的
通过many-to-one元素,可以定义一种常见的与另一个持久化类的关联。 这种关系模型是多对一关联(实际上是一个对象引用-译注):这个表的一个外键引用目标表的 主键字段。
(1) column="column_name" (2) class="ClassName" (3) cascade="cascade_style" (4) fetch="join|select" (5) update="true|false" (6) insert="true|false" (6) property-ref="propertyNameFromAssociatedClass" (7) access="field|property|ClassName" (8) unique="true|false" (9) not-null="true|false" (10) optimistic-lock="true|false" (11) lazy="true|proxy|false" (12) not-found="ignore|exception" (13) entity-name="EntityName" (14) node="element-name|@attribute-name|element/@attribute|." embed-xml="true|false" />
(1) | name: 属性名。 |
(2) | column (可选): 外间字段名。它也可以通过嵌套的 |
(3) | class (可选 - 默认是通过反射得到属性类型): 关联的类的名字。 |
(4) | cascade(级联) (可选): 指明哪些操作会从父对象级联到关联的对象。 |
(5) | fetch (可选 - 默认为 select): 在外连接抓取(outer-join fetching)和序列选择抓取(sequential select fetching)两者中选择其一。 |
(6) | update, insert (可选 - defaults to true) 指定对应的字段是否包含在用于UPDATE 和/或 INSERT 的SQL语句中。如果二者都是false,则这是一个纯粹的 “外源性(derived)”关联,它的值是通过映射到同一个(或多个)字段的某些其他属性得到 或者通过trigger(触发器)、或其他程序。 |
(7) | property-ref: (可选) 指定关联类的一个属性,这个属性将会和本外键相对应。 如果没有指定,会使用对方关联类的主键。 |
(8) | access (可选 - 默认是 property): Hibernate用来访问属性的策略。 |
(9) | unique (可选): 使用DDL为外键字段生成一个唯一约束。此外, 这也可以用作property-ref的目标属性。这使关联同时具有 一对一的效果。 |
(10) | not-null (可选): 使用DDL为外键字段生成一个非空约束。 |
(11) | optimistic-lock (可选 - 默认为 true): 指定这个属性在做更新时是否需要获得乐观锁定(optimistic lock)。 换句话说,它决定这个属性发生脏数据时版本(version)的值是否增长。 |
(12) | lazy (可选 - 默认为 proxy): 默认情况下,单点关联是经过代理的。lazy="true"指定此属性应该在实例变量第一次被访问时应该延迟抓取(fetche lazily)(需要运行时字节码的增强)。 lazy="false"指定此关联总是被预先抓取。 |
(13) | not-found (可选 - 默认为 exception): 指定外键引用的数据不存在时如何处理: ignore会将数据不存在作为关联到一个空对象(null)处理。 |
(14) | entity-name (optional): 被关联的类的实体名。 |
cascade属性设置为除了none以外任何有意义的值, 它将把特定的操作传播到关联对象中。这个值就代表着Hibernate基本操作的名称, persist, merge, delete, save-update, evict, replicate, lock, refresh, 以及特别的值delete-orphan和all,并且可以用逗号分隔符 来合并这些操作,例如,cascade="persist,merge,evict"或 cascade="all,delete-orphan"。更全面的解释请参考第 11.11 节 “传播性持久化(transitive persistence)”.
一个典型的简单many-to-one定义例子:
property-ref属性只应该用来对付老旧的数据库系统, 可能有外键指向对方关联表的是个非主键字段(但是应该是一个惟一关键字)的情况下。 这是一种十分丑陋的关系模型。比如说,假设Product类有一个惟一的序列号, 它并不是主键。(unique属性控制Hibernate通过SchemaExport工具生成DDL的过程。)
那么关于OrderItem 的映射可能是:
当然,我们决不鼓励这种用法。
如果被引用的唯一主键由关联实体的多个属性组成,你应该在名称为
持久化对象之间一对一的关联关系是通过one-to-one元素定义的。
(1) class="ClassName" (2) cascade="cascade_style" (3) constrained="true|false" (4) fetch="join|select" (5) property-ref="propertyNameFromAssociatedClass" (6) access="field|property|ClassName" (7) formula="any SQL expression" (8) lazy="true|proxy|false" (9) entity-name="EntityName" (10) node="element-name|@attribute-name|element/@attribute|." embed-xml="true|false" />
(1) | name: 属性的名字。 |
(2) | class (可选 - 默认是通过反射得到的属性类型):被关联的类的名字。 |
(3) | cascade(级联) (可选) 表明操作是否从父对象级联到被关联的对象。 |
(4) | constrained(约束) (可选) 表明该类对应的表对应的数据库表,和被关联的对象所对应的数据库表之间,通过一个外键引用对主键进行约束。 这个选项影响save()和delete()在级联执行时的先后顺序以及 决定该关联能否被委托(也在schema export tool中被使用). |
(5) | fetch (可选 - 默认设置为选择): 在外连接抓取或者序列选择抓取选择其一. |
(6) | property-ref: (可选) 指定关联类的属性名,这个属性将会和本类的主键相对应。如果没有指定,会使用对方关联类的主键。 |
(7) | access (可选 - 默认是 |