<composite-id name="propertyName" class="ClassName" unsaved-value="any|none"> <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()持久化状态之前,必须填充他的联合属性。我们会在Section 7.4, “作为联合标识符(As Composite Identifiers)”章中说明一种更加方便的方法,把联合标识实现为一个独立的类,下面描述的属性只对这种备用方法有效:
name (可选):一个组件类型,持有联合标识(参见下一节)。
class (可选 - 默认为通过反射(reflection)得到的属性类型) : 作为联合标识的组件类名(参见下一节)。
unsaved-value (可选 - 默认为 none): 假如被设置为非none的值,就表示新创建,尚未被持久化的实例将持有的值。
在"一棵对象继承树对应一个表"的策略中,<discriminator>元素是必需的,它声明了表的识别器字段。识别器字段包含标志值,用于告知持久化层应该为某个特定的行创建哪一个子类的实例。只能使用如下受到限制的一些类型: string, character, integer, byte, short, boolean, yes_no, true_false.
<discriminator column="discriminator_column"type="discriminator_type"
force="true|false"
/>
![]() |
column (可选 - 默认为 class) 识别器字段的名字 |
![]() |
type (可选 - 默认为 string) 一个Hibernate字段类型的名字 |
![]() |
force(强制) (可选 - 默认为 false) "强制"Hibernate指定允许的识别器值,就算取得的所有实例都是根类的。 |
标识器字段的实际值是根据<class> 和<subclass>元素的discriminator-value得来的.
force属性仅仅是在表包含一些未指定应该映射到哪个持久化类的时候才是有用的。这种情况不是经常会遇到。
<version>元素是可选的,表明表中包含附带版本信息的数据。这在你准备使用 长事务(long transactions)的时候特别有用。(见后)
<version column="version_column"name="propertyName"
type="typename"
access="field|property|ClassName"
unsaved-value="null|negative|undefined"
/>
![]() |
column (可选 - 默认为属性名): 指定持有版本号的字段名。 |
![]() |
name: 持久化类的属性名。 |
![]() |
type (可选 - 默认是 integer): 版本号的类型。 |
![]() |
access (可选 - 默认是 property): Hibernate用于访问属性值的策略。 |
![]() |
unsaved-value (可选 - 默认是undefined): 用于标明某个实例时刚刚被实例化的(尚未保存)版本属性值,依靠这个值就可以把这种情况和已经在先前的session中保存或装载的实例区分开来。(undefined指明使用标识属性值进行这种判断。) |
版本号必须是以下类型:long, integer, short, timestamp或者calendar。
可选的<timestamp>元素指明了表中包含时间戳数据。这用来作为版本的替代。时间戳本质上是一种对乐观锁定的一种不是特别安全的实现。当然,有时候应用程序可能在其他方面使用时间戳。
<timestamp column="timestamp_column"name="propertyName"
access="field|property|ClassName"
unsaved-value="null|undefined"
/>
![]() |
column (可选 - 默认为属性名): 持有时间戳的字段名。 |
![]() |
name: 在持久化类中的JavaBeans风格的属性名,其Java类型是 Date 或者 Timestamp的。 |
![]() |
access (可选 - 默认是 property): Hibernate用于访问属性值的策略。 |
![]() |
unsaved-value (可选 - 默认是null): 用于标明某个实例时刚刚被实例化的(尚未保存)版本属性值,依靠这个值就可以把这种情况和已经在先前的session中保存或装载的实例区分开来。(undefined指明使用标识属性值进行这种判断。) |
注意,<timestamp> 和<version type="timestamp">是等价的。
<property>元素为类声明了一个持久化的,JavaBean风格的属性。
<property name="propertyName"column="column_name"
type="typename"
update="true|false"
insert="true|false"
formula="arbitrary SQL expression"
access="field|property|ClassName"
/>
![]() |
name: 属性的名字,以小写字母开头。 |
![]() |
column (可选 - 默认为属性名字): 对应的数据库字段名。 |
![]() |
type (可选): 一个Hibernate类型的名字。 |
![]() |
update, insert (可选 - 默认为 true) :表明在用于UPDATE 和/或 INSERT的SQL语句中是否包含这个字段。这二者如果都设置为false则表明这是一个“外源性(derived)”的属性,它的值来源于映射到同一个(或多个)字段的某些其他属性,或者通过一个trigger(触发器),或者其他程序。 |
![]() |
formula (可选): 一个SQL表达式,定义了这个计算(computed) 属性的值。计算属性没有和它对应的数据库字段。 |
![]() |
access (可选 - 默认值为 property): Hibernate用来访问属性值的策略。 |
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)。
一个PersistentEnum的子类的名字。(比如:. eg.Color)。
一个可以序列化的Java类的名字。
一个自定义类型的类的名字。(比如: com.illflow.type.MyCustomType)。
如果你没有指定类型,Hibernarte会使用反射来得到这个名字的属性,以此来猜测正确的Hibernate类型。Hibernate会对属性读取器(getter方法)的返回类进行解释,按照规则2,3,4的顺序。然而,这并不足够。 在某些情况下你仍然需要type属性。(比如,为了区别Hibernate.DATE和Hibernate.TIMESTAMP,或者为了指定一个自定义类型。)
access属性用来让你控制Hibernate如何在运行时访问属性。在默认情况下,Hibernate会使用属性的get/set方法对。如果你指明access="field",Hibernate会忽略get/set方法对,直接使用反射来访问成员变量。你也可以指定你自己的策略,这就需要你自己实现net.sf.hibernate.property.PropertyAccessor接口,再在access中设置你自定义策略类的名字。