我们将向Person类增加一连串的events。那样,通过调用aPerson.getEvents(),就可以轻松地导航到特定person所参与的events,而不用去执行一个显式的查询。我们使用Java的集合类(collection):Set,因为set 不包含重复的元素及与我们无关的排序。
我们需要用set 实现一个单向多值关联。让我们在Java类里为这个关联编码,接着映射它:
public class Person { private Set events = new HashSet(); public Set getEvents() { return events; } public void setEvents(Set events) { this.events = events; } }
在映射这个关联之前,先考虑一下此关联的另外一端。很显然,我们可以保持这个关联是单向的。或者,我们可以在Event里创建另外一个集合,如果希望能够双向地导航,如:anEvent.getParticipants()。从功能的角度来说,这并不是必须的。因为你总可以显式地执行一个查询,以获得某个特定event的所有参与者。这是个在设计时需要做出的选择,完全由你来决定,但此讨论中关于关联的阶数是清楚的:即两端都是“多”值的,我们把它叫做多对多(many-to-many)关联。因而,我们使用Hibernate的多对多映射:
<class name="events.Person" table="PERSON"> <id name="id" column="PERSON_ID"> <generator class="native"/> </id> <property name="age"/> <property name="firstname"/> <property name="lastname"/> <set name="events" table="PERSON_EVENT"> <key column="PERSON_ID"/> <many-to-many column="EVENT_ID" class="events.Event"/> </set> </class>
Hibernate支持各种各样的集合映射,<set>使用的最为普遍。对于多对多关联(或叫n:m实体关系), 需要一个关联表(association table)。表里面的每一行代表从person到event的一个关联。表名是由set元素的table属性配置的。关联里面的标识符字段名,对于person的一端,是由<key>元素定义,而event一端的字段名是由<many-to-many>元素的column属性定义。你也必须告诉Hibernate集合中对象的类(也就是位于这个集合所代表的关联另外一端的类)。
因而这个映射的数据库schema是:
_____________ __________________ | | | | _____________ | EVENTS | | PERSON_EVENT | | | |_____________| |__________________| | PERSON | | | | | |_____________| | *EVENT_ID | <--> | *EVENT_ID | | | | EVENT_DATE | | *PERSON_ID | <--> | *PERSON_ID | | TITLE | |__________________| | AGE | |_____________| | FIRSTNAME | | LASTNAME | |_____________|