📄 components.html
字号:
<html><head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>第 8 章 组件(Component)映射</title><link rel="stylesheet" href="../shared/css/html.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.65.1"><link rel="home" href="index.html" title="HIBERNATE - 符合Java习惯的关系数据库持久化"><link rel="up" href="index.html" title="HIBERNATE - 符合Java习惯的关系数据库持久化"><link rel="previous" href="associations.html" title="第 7 章 关联关系映射"><link rel="next" href="inheritance.html" title="第 9 章 继承映射(Inheritance Mappings)"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">第 8 章 组件(Component)映射</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="associations.html">上一页</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="inheritance.html">下一页</a></td></tr></table><hr></div><div class="chapter" lang="zh-cn"><div class="titlepage"><div><div><h2 class="title"><a name="components"></a>第 8 章 组件(Component)映射</h2></div></div><div></div></div><p> <span class="emphasis"><em>组件</em></span>(Component)这个概念在Hibernate中几处不同的地方为了不同的目的被重复使用. </p><div class="sect1" lang="zh-cn"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="components-dependentobjects"></a>8.1. 依赖对象(Dependent objects)</h2></div></div><div></div></div><p> 组件(Component)是一个被包含的对象,在持久化的过程中,它被当作值类型,而并非一个实体的引用。在这篇文档中,组件这一术语指的是面向对象的合成概念(而并不是系统构架层次上的组件的概念)。举个例子, 你对人(Person)这个概念可以像下面这样来建模: </p><pre class="programlisting">public class Person { private java.util.Date birthday; private Name name; private String key; public String getKey() { return key; } private void setKey(String key) { this.key=key; } public java.util.Date getBirthday() { return birthday; } public void setBirthday(java.util.Date birthday) { this.birthday = birthday; } public Name getName() { return name; } public void setName(Name name) { this.name = name; } ...... ......}</pre><pre class="programlisting">public class Name { char initial; String first; String last; public String getFirst() { return first; } void setFirst(String first) { this.first = first; } public String getLast() { return last; } void setLast(String last) { this.last = last; } public char getInitial() { return initial; } void setInitial(char initial) { this.initial = initial; }}</pre><p> 在持久化的过程中,<tt class="literal">姓名(Name)</tt>可以作为<tt class="literal">人(Person)</tt>的一个组件。需要注意的是:你应该为<tt class="literal">姓名</tt>的持久化属性定义getter和setter方法,但是你不需要实现任何的接口或申明标识符字段。 </p><p> 以下是这个例子的Hibernate映射文件: </p><pre class="programlisting"><class name="eg.Person" table="person"> <id name="Key" column="pid" type="string"> <generator class="uuid"/> </id> <property name="birthday" type="date"/> <component name="Name" class="eg.Name"> <!-- class attribute optional --> <property name="initial"/> <property name="first"/> <property name="last"/> </component></class></pre><p> 人员(Person)表中将包括<tt class="literal">pid</tt>, <tt class="literal">birthday</tt>, <tt class="literal">initial</tt>, <tt class="literal">first</tt>和 <tt class="literal">last</tt>等字段。</p><p> 就像所有的值类型一样, 组件不支持共享引用。 换句话说,两个人可能重名,但是两个Person对象应该包含两个独立的Name对象,只不过这两个Name对象具有“同样”的值。 组件的值可以为空,其定义如下。 每当Hibernate重新加载一个包含组件的对象,如果该组件的所有字段为空,Hibernate将假定整个组件为空。 在大多数情况下,这样假定应该是没有问题的。 </p><p> 组件的属性可以是任意一种Hibernate类型(包括集合, 多对多关联, 以及其它组件等等)。嵌套组件不应该被当作一种特殊的应用(Nested components should not be considered an exotic usage)。 Hibernate倾向于支持细致的(fine-grained)对象模型。 </p><p> <tt class="literal"><component></tt> 元素还允许有 <tt class="literal"><parent></tt>子元素,用来表明component类中的一个属性是指向包含它的实体的引用。 </p><pre class="programlisting"><class name="eg.Person" table="person"> <id name="Key" column="pid" type="string"> <generator class="uuid"/> </id> <property name="birthday" type="date"> <component name="Name" class="eg.Name" unique="true"> <parent name="namedPerson"/> <!-- reference back to the Person --> <property name="initial"/> <property name="first"/> <property name="last"/> </component&gt;</class></pre></div><div class="sect1" lang="zh-cn"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="components-incollections"></a>8.2. 在集合中出现的依赖对象 (Collections of dependent objects)</h2></div></div><div></div></div><p> Hibernate支持组件的集合(例如: 一个元素是姓名(Name)这种类型的数组)。 你可以使用<tt class="literal"><composite-element></tt>标签替代<tt class="literal"><element></tt>标签来定义你的组件集合。 </p><pre class="programlisting"><set name="someNames" table="some_names" lazy="true"> <key column="id"/&gt; <composite-element class="eg.Name"> <!-- class attribute required --> <property name="initial"/> <property name="first"/> <property name="last"/>; </composite-element></set></pre><p> 注意,如果你定义的Set包含组合元素(composite-element),正确地实现<tt class="literal">equals()</tt>和<tt class="literal">hashCode()</tt>是非常重要的。 </p><p> 组合元素可以包含组件,但是不能包含集合。如果你的组合元素自身包含组件, 你必须使用<tt class="literal"><nested-composite-element></tt>标签。这是一个相当特殊的案例 - 在一个组件的集合里,那些组件本身又可以包含其他的组件。这个时候你就应该考虑一下使用one-to-many关联是否会更恰当。 尝试对这个组合元素重新建模为一个实体-但是需要注意的是,虽然Java模型和重新建模前是一样的,关系模型和持久性语义会有细微的变化。 </p><p> 请注意如果你使用<tt class="literal"><set></tt>标签,一个组合元素的映射不支持可能为空的属性. 当删除对象时, Hibernate必须使用每一个字段的值来确定一条记录(在组合元素表中,没有单独的关键字段), 如果有为null的字段,这样做就不可能了。你必须作出一个选择,要么在组合元素中使用不能为空的属性,要么选择使用<tt class="literal"><list></tt>,<tt class="literal"><map></tt>,<tt class="literal"><bag></tt> 或者 <tt class="literal"><idbag></tt>而不是 <tt class="literal"><set></tt>。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -