ThinkSSL🔒 一键申购 5分钟快速签发 30天无理由退款 购买更放心 广告
# 5.1.10\. 多对一(many-to-one) 通过`many-to-one`元素,可以定义一种常见的与另一个持久化类的关联。 这种关系模型是多对一关联(实际上是一个对象引用-译注):这个表的一个外键引用目标表的 主键字段。 ``` <many-to-one name="propertyName" column="column_name" class="ClassName" cascade="cascade_style" fetch="join|select" update="true|false" insert="true|false" property-ref="propertyNameFromAssociatedClass" access="field|property|ClassName" unique="true|false" not-null="true|false" optimistic-lock="true|false" lazy="proxy|no-proxy|false" not-found="ignore|exception" entity-name="EntityName" formula="arbitrary SQL expression" node="element-name|@attribute-name|element/@attribute|." embed-xml="true|false" index="index_name" unique_key="unique_key_id" foreign-key="foreign_key_name" /> ``` | ![1](img/1.png) | `name`: 属性名。 | |:--- |:--- | | ![2](img/2.png) | `column` (可选): 外间字段名。它也可以通过嵌套的 `&lt;column&gt;`元素指定。 | | ![3](img/3.png) | `class` (可选 - 默认是通过反射得到属性类型): 关联的类的名字。 | | ![4](img/4.png) | `cascade(级联)` (可选): 指明哪些操作会从父对象级联到关联的对象。 | | ![5](img/5.png) | `fetch` (可选 - 默认为 `select`): 在外连接抓取(outer-join fetching)和序列选择抓取(sequential select fetching)两者中选择其一。 | | ![6](img/6.png) | `update, insert` (可选 - 默认为 `true`) 指定对应的字段是否包含在用于`UPDATE` 和/或 `INSERT` 的SQL语句中。如果二者都是`false`,则这是一个纯粹的 “外源性(derived)”关联,它的值是通过映射到同一个(或多个)字段的某些其他属性得到 或者通过trigger(触发器)、或其他程序生成。 | | ![6](img/6.png) | `property-ref`: (可选) 指定关联类的一个属性,这个属性将会和本外键相对应。 如果没有指定,会使用对方关联类的主键。 | | ![7](img/7.png) | `access` (可选 - 默认是 `property`): Hibernate用来访问属性的策略。 | | ![8](img/8.png) | `unique` (可选): 使用DDL为外键字段生成一个唯一约束。此外, 这也可以用作`property-ref`的目标属性。这使关联同时具有 一对一的效果。 | | ![9](img/9.png) | `not-null` (可选): 使用DDL为外键字段生成一个非空约束。 | | ![10](img/10.png) | `optimistic-lock` (可选 - 默认为 `true`): 指定这个属性在做更新时是否需要获得乐观锁定(optimistic lock)。 换句话说,它决定这个属性发生脏数据时版本(version)的值是否增长。 | | ![11](img/11.png) | `lazy` (可选 - 默认为 `proxy`): 默认情况下,单点关联是经过代理的。`lazy="no-proxy"`指定此属性应该在实例变量第一次被访问时应该延迟抓取(fetche lazily)(需要运行时字节码的增强)。 `lazy="false"`指定此关联总是被预先抓取。 | | ![12](img/12.png) | `not-found` (可选 - 默认为 `exception`): 指定外键引用的数据不存在时如何处理: `ignore`会将行数据不存在视为一个空(null)关联。 | | ![13](img/13.png) | `entity-name` (可选): 被关联的类的实体名。 | | ![14](img/14.png) | `formula` (可选): SQL表达式,用于定义_computed(计算出的)_外键值。 | `cascade`属性设置为除了`none`以外任何有意义的值, 它将把特定的操作传递到关联对象中。这个值就代表着Hibernate基本操作的名称, `persist, merge, delete, save-update, evict, replicate, lock, refresh`, 以及特别的值`delete-orphan`和`all`,并且可以用逗号分隔符 来组合这些操作,例如,`cascade="persist,merge,evict"`或 `cascade="all,delete-orphan"`。更全面的解释请参考[第 10.11 节 “传播性持久化(transitive persistence)”](../Text/pr01_split_000.html "10.11\. 传播性持久化(transitive persistence)"). 注意,单值关联 (many-to-one 和 one-to-one 关联) 不支持删除孤儿(orphan delete,删除不再被引用的值). 一个典型的简单`many-to-one`定义例子: ``` <many-to-one name="product" class="Product" column="PRODUCT_ID"/> ``` `property-ref`属性只应该用来对付遗留下来的数据库系统, 可能有外键指向对方关联表的是个非主键字段(但是应该是一个惟一关键字)的情况下。 这是一种十分丑陋的关系模型。比如说,假设`Product`类有一个惟一的序列号, 它并不是主键。(`unique`属性控制Hibernate通过SchemaExport工具进行的DDL生成。) ``` <property name="serialNumber" unique="true" type="string" column="SERIAL_NUMBER"/> ``` 那么关于`OrderItem` 的映射可能是: ``` <many-to-one name="product" property-ref="serialNumber" column="PRODUCT_SERIAL_NUMBER"/> ``` 当然,我们决不鼓励这种用法。 如果被引用的唯一主键由关联实体的多个属性组成,你应该在名称为`&lt;properties&gt;`的元素 里面映射所有关联的属性。 假若被引用的唯一主键是组件的属性,你可以指定属性路径: ``` <many-to-one name="owner" property-ref="identity.ssn" column="OWNER_SSN"/> ```