映射实体关联
您需要管理应用程序中这些持久性类之间的关系。
持久性类也称作“实体类”。
为此,Hibernate 允许您在映射文件中将实体类间的关系映射到各表间的关系。
Hibernate 允许您在Hibernate 映射文件中映射数据库表间的关系。
这些关系可以是以下某种类型:
一对一
一对多
多对多
一对一关联
您需要在Hibernate 映射文件中映射Java 类之间的一对一关联。
为此,您可以在Hibernate 映射文件中使用<many-to-one>
元素。
此元素包含以下属性:
name指定用于关联类的属性名称。
class指定为name属性指定的属性提供值的相关类的完全限定名。
column指定外键列的名称,它存储name属性指定的属性的值。
cascade指定在一个表上执行的操作也会影响有类似更新的另一个表。
unique指定外键列包含唯一的值。此属性使得表之间的链接为一对一关联。
not-null指定如果设置为true,外键列就不能包含null 值。
<hibernate-mapping>
<class name="Test.Person" table="PERSON">
<id name="personID" type="string"><column name="PERSONID" length="10" />
<generator class="assigned" />
</id>
<property name="personName" type="string"><column name="PERSONNAME" length="40" />
</property>
<many-to-one name="personDetail" class="Test.PersonInfo" column="personDetailID" not-null="true" cascade="all" unique="true" />
</class>
</hibernate-mapping>
表示使用元素在PERSON 表和PERSONINFO 表之间映射一对一关联。该元素的unique属性指定在PERSON 表中为PERSONINFO 表中PERSONDETAILID 列的每个值存在唯一的值。
一对多关联:
您可以使用Hibernate 映射文件中的<one-to-many>
元素将类与包含一对多关系的数据库中的表映射起来,如以下代码段所示:
<hibernate-mapping>
<class name="Test.Authors" table="AUTHORS">
......
<set cascade="all" name="BOOKS">
<key column="authorid"/>
<one-to-many class="Test.Books"/>
</set>
</class>
<class name="Test.Books" table="Books">
......
</class>
</hibernate-mapping>
<one-to-many>
元素用于将Authors和Books类分别映射到AUTHORS 表和BOOKS 表。
多对多关联:
您可以使用Hibernate 映射文件中的<many-to-many>
元素将类与包含多对多关系的数据库中的表映射起来,如以下代码段所示:
<hibernate-mapping>
<class name="Test.Student" table="STUDENT">
......
<set cascade="all" name="courses" table="REGISTRATION">
<key column="STUDENTID"/>
<many-to-many class="Test.Course" column="COURSEID"/>
</set>
</class>
</hibernate-mapping>
<many-to-many>
元素用于映射Student类和Course类之间的关联。
映射类继承
通过继承关系使Java 类相互关联。
然而,继承关系不能在数据库的各表间实现。
因此,您需要在映射类和数据库表时,在Hibernate 映射文件中显式映射类的继承关系。
Hibernate 提供以下映射类型来支持继承层次结构:
每个具体类一张表:
在每个具体类一张表映射中,在继承层次结构中为每个类创建一张表。
每张表为类的所有属性(包括继承属性)定义了列。
在创建了表和类之后,您需要在Hibernate 映射文件中映射它们。
您可以使用<union-subclass>
元素在映射文件中映射子类。
这个元素包含以下常用属性:
name指定子类的名称。
table指定将与子类映射的表的名称
例如:
<hibernate-mapping>
<class name="Test.Books" table="BOOKS">
......
<union-subclass name="Test.SEBooks" table="SEBOOKS">
<property name="specialFeatures" type="string">
<column length="200" name="SPECIALFEATURES"/>
</property>
</union-subclass>
<union-subclass name="Test.INBooks" table="INBOOKS">
<property name="bookLanguage" type="string">
<column length="20" name="BOOKLANGUAGE"/>
</property>
</union-subclass>
</class>
</hibernate-mapping>
<class>
元素提供了超类Book的映射信息。
<union-subclass>
元素用于将每个子类与数据库中相应的表映射。
上述代码中,<class>
元素提供了父类Book的映射信息。<union-subclass>
元素继承父类的属性。
因此,它不映射已由<class>
元素映射的属性
实现每个具体类一张表映射策略具有以下缺点:
对于在超类中映射的每个属性而言,所有子类表中的列名必须是相同的。
每张表为类的所有属性(包括继承属性)定义了列。这就造成了值的重复。
需要单独的查询来从存储具体类的数据的每个表检索数据。
超类属性中的更改会造成子类表的各个列的更改。
每个类一张表:
在每个类层次结构一张表映射策略中,在继承层次结构中为所有类创建一张表。
这就不会造成为类层次结构中的每个类创建的表中有重复的列名。
然而,您需要在区分子类的对象的表中创建额外的列。
此列称作“鉴别器”。
存储在此列中的值用于识别子类所表示的行。
以下元素用于实现每个类层次结构一张表映射:
<discriminator>
:借助以下属性指定鉴别器列的设置:
column指定鉴别器列的名称
type指定存储在鉴别器列中的值的数据类型
<subclass>
:借助以下属性指定子类的设置:
name指定子类的名称。
discriminator-value指定用于当前子类的鉴别器值。
例如:
<hibernate-mapping>
<class name="Test.Books" table="BOOKDETAILS">
......
<discriminator column="BOOKTYPE" type= "string"/>
......
<subclass name="Test.SEBooks" discriminator-value="SE"> ...... </subclass>
<subclass name="Test.INBooks" discriminator-value="IN"> ...... </subclass>
</class>
</hibernate-mapping>
每个类层次结构一张表简化了映射,而且您无需用重复的列名创建多个表。
然而,如果继承层次结构增加了,而且包含多个类,表的大小就增加了。
此外,在为继承层次结构中的所有类创建单个表时,类中不常见的列包含null 值。
因此,如果类层次结构增加,存储在表中的null 值的数量也会增加。这会影响数据库的数据完整性。
每个子类一张表:
在每个子类一张表映射策略中,为每个类创建单个表。
然而,不会为存储子类的对象的表中的继承属性重复列。
存储超类的对象的表包含主键,它用作存储子类对象的表中的外键。
要实现每个子类一张表映射,您需要使用Hibernate 映射文件中的<joined-subclass>
元素。
例如:
<hibernate-mapping>
<class name="Test.Books" table="BOOKS">
......
<property name="bookTitle" type="string">
<column length="20" name="BOOKTITLE"/>
</property>
......
<joined-subclass name="Test.SEBooks" table="SEBOOKS">
<key column="seBookID"/>
<property name="specialFeatures" type="string">
<column length="200" name="SPECIALFEATURES"/>
</property>
</joined-subclass>
......
</class>
</hibernate-mapping>
<key>
指定外键列的名称
<joined-subclass>
映射Book类的子类
在每个子类一张表中,在表中使用外键关联来映射继承关系。
存储子类对象的表无需单独的查询。
如果超类的属性更改了,您无需在存储子类对象的表的列中作出任何更改。