collections.html
来自「是一个中文的Hibernate库文档」· HTML 代码 · 共 521 行 · 第 1/5 页
HTML
521 行
要建立一个双向的多对多关联,只需要映射两个many-to-many关联到同一个数据库表中,并再定义其中的一端为<span class="emphasis"><em>inverse</em></span>(使用哪一端要根据你的选择,但它不能是一个索引集合)。 </p><p> 这里有一个many-to-many的双向关联的例子;每一个category都可以有很多items,每一个items可以属于很多categories: </p><pre class="programlisting"><class name="Category"> <id name="id" column="CATEGORY_ID"/> ... <bag name="items" table="CATEGORY_ITEM"> <key column="CATEGORY_ID"/> <many-to-many class="Item" column="ITEM_ID"/> </bag></class><class name="Item"> <id name="id" column="CATEGORY_ID"/> ... <!-- inverse end --> <bag name="categories" table="CATEGORY_ITEM" inverse="true"> <key column="ITEM_ID"/> <many-to-many class="Category" column="CATEGORY_ID"/> </bag></class></pre><p> 如果只对关联的反向端进行了改变,这个改变<span class="emphasis"><em>不会</em></span>被持久化。 这表示Hibernate为每个双向关联在内存中存在两次表现,一个从A连接到B,另一个从B连接到A。如果你回想一下Java对象模型,我们是如何在Java中创建多对多关系的,这可以让你更容易理解: </p><pre class="programlisting">category.getItems().add(item); // The category now "knows" about the relationshipitem.getCategories().add(category); // The item now "knows" about the relationshipsession.persist(item); // The relationship won''t be saved!session.persist(category); // The relationship will be saved</pre><p> 非反向端用于把内存中的表示保存到数据库中。 </p><p> 要建立一个一对多的双向关联,你可以通过把一个一对多关联,作为一个多对一关联映射到到同一张表的字段上,并且在"多"的那一端定义<tt class="literal">inverse="true"</tt>。 </p><pre class="programlisting"><class name="Parent"> <id name="id" column="parent_id"/> .... <set name="children" inverse="true"> <key column="parent_id"/> <one-to-many class="Child"/> </set></class><class name="eg.Child"> <id name="id" column="id"/> .... <many-to-one name="parent" class="Parent" column="parent_id" not-null="true"/></class></pre><p> 在“一”这一端定义<tt class="literal">inverse="true"</tt>不会影响级联操作,二者是正交的概念! </p></div><div class="sect2" lang="zh-cn"><div class="titlepage"><div><div><h3 class="title"><a name="collections-ternary"></a>7.3.3. 三重关联(Ternary associations)</h3></div></div><div></div></div><p> 有三种可能的途径来映射一个三重关联。第一种是使用一个<tt class="literal">Map</tt>,把一个关联作为其索引: </p><pre class="programlisting"><map name="contracts"> <key column="employer_id" not-null="true"/> <map-key-many-to-many column="employee_id" class="Employee"/> <one-to-many class="Contract"/></map></pre><pre class="programlisting"><map name="connections"> <key column="incoming_node_id"/> <map-key-many-to-many column="outgoing_node_id" class="Node"/> <many-to-many column="connection_id" class="Connection"/></map></pre><p> 第二种方法是简单的把关联重新建模为一个实体类。这使我们最经常使用的方法。 </p><p> 最后一种选择是使用复合元素,我们会在后面讨论 </p></div><div class="sect2" lang="zh-cn"><div class="titlepage"><div><div><h3 class="title"><a name="collections-idbag"></a>7.3.4. <tt class="literal">使用<idbag></tt></h3></div></div><div></div></div><p> 如果你完全信奉我们对于“联合主键(composite keys)是个坏东西”,和“实体应该使用(无机的)自己生成的代用标识符(surrogate keys)”的观点,也许你会感到有一些奇怪,我们目前为止展示的多对多关联和值集合都是映射成为带有联合主键的表的!现在,这一点非常值得争辩;看上去一个单纯的关联表并不能从代用标识符中获得什么好处(虽然使用组合值的集合<span class="emphasis"><em>可能</em></span>会获得一点好处)。不过,Hibernate提供了一个(一点点试验性质的)功能,让你把多对多关联和值集合应得到一个使用代用标识符的表去。 </p><p> <tt class="literal"><idbag></tt> 属性让你使用bag语义来映射一个<tt class="literal">List</tt> (或<tt class="literal">Collection</tt>)。 </p><pre class="programlisting"><idbag name="lovers" table="LOVERS"> <collection-id column="ID" type="long"> <generator class="sequence"/> </collection-id> <key column="PERSON1"/> <many-to-many column="PERSON2" class="eg.Person" outer-join="true"/></idbag></pre><p> 你可以理解,<tt class="literal"><idbag></tt>人工的id生成器,就好像是实体类一样!集合的每一行都有一个不同的人造关键字。但是,Hibernate没有提供任何机制来让你取得某个特定行的人造关键字。 </p><p> 注意<tt class="literal"><idbag></tt>的更新性能要比普通的<tt class="literal"><bag></tt>高得多!Hibernate可以有效的定位到不同的行,分别进行更新或删除工作,就如同处理一个list, map或者set一样。 </p><p> 在目前的实现中,还不支持使用<tt class="literal">identity</tt>标识符生成器策略来生成<tt class="literal"><idbag></tt>集合的标识符。 </p></div></div><div class="sect1" lang="zh-cn"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="collections-example"></a>7.4. 集合例子(Collection example)</h2></div></div><div></div></div><p> 在前面的几个章节的确非常令人迷惑。 因此让我们来看一个例子。这个类: </p><pre class="programlisting">package eg;import java.util.Set;public class Parent { private long id; private Set children; public long getId() { return id; } private void setId(long id) { this.id=id; } private Set getChildren() { return children; } private void setChildren(Set children) { this.children=children; } .... ....}</pre><p> 这个类有一个<tt class="literal">Child</tt>的实例集合。如果每一个子实例至多有一个父实例, 那么最自然的映射是一个one-to-many的关联关系: </p><pre class="programlisting"><hibernate-mapping> <class name="Parent">
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?