1.3.2. 单向Set-based的关联

我们将向Person类增加一连串的events。那样,通过调用aPerson.getEvents(),就可以轻松地导航到特定person所参与的events,而不用去执行一个显式的查询。我们使用Java的集合类(collection):Set,因为set 不包含重复的元素及与我们无关的排序。

我们需要用set 实现一个单向多值关联。让我们在Java类里为这个关联编码,接着映射它:

  1. public class Person {
  2. private Set events = new HashSet();
  3. public Set getEvents() {
  4. return events;
  5. }
  6. public void setEvents(Set events) {
  7. this.events = events;
  8. }
  9. }

在映射这个关联之前,先考虑一下此关联的另外一端。很显然,我们可以保持这个关联是单向的。或者,我们可以在Event里创建另外一个集合,如果希望能够双向地导航,如:anEvent.getParticipants()。从功能的角度来说,这并不是必须的。因为你总可以显式地执行一个查询,以获得某个特定event的所有参与者。这是个在设计时需要做出的选择,完全由你来决定,但此讨论中关于关联的阶数是清楚的:即两端都是“多”值的,我们把它叫做多对多(many-to-many)关联。因而,我们使用Hibernate的多对多映射:

  1. <class name="events.Person" table="PERSON">
  2. <id name="id" column="PERSON_ID">
  3. <generator class="native"/>
  4. </id>
  5. <property name="age"/>
  6. <property name="firstname"/>
  7. <property name="lastname"/>
  8. <set name="events" table="PERSON_EVENT">
  9. <key column="PERSON_ID"/>
  10. <many-to-many column="EVENT_ID" class="events.Event"/>
  11. </set>
  12. </class>

Hibernate支持各种各样的集合映射,&lt;set&gt;使用的最为普遍。对于多对多关联(或叫n:m实体关系), 需要一个关联表(association table)。里面的每一行代表从person到event的一个关联。表名是由set元素的table属性配置的。关联里面的标识符字段名,对于person的一端,是由&lt;key&gt;元素定义,而event一端的字段名是由&lt;many-to-many&gt;元素的column属性定义。你也必须告诉Hibernate集合中对象的类(也就是位于这个集合所代表的关联另外一端的类)。

因而这个映射的数据库schema是:

  1. _____________ __________________
  2. | | | | _____________
  3. | EVENTS | | PERSON_EVENT | | |
  4. |_____________| |__________________| | PERSON |
  5. | | | | |_____________|
  6. | *EVENT_ID | <--> | *EVENT_ID | | |
  7. | EVENT_DATE | | *PERSON_ID | <--> | *PERSON_ID |
  8. | TITLE | |__________________| | AGE |
  9. |_____________| | FIRSTNAME |
  10. | LASTNAME |
  11. |_____________|