1.对象关系映射基础
1.1 持久化类的属性及访问方法
持久化类的访问方法有两个调用者:
- java应用程序:通过持久化类的getter和setter方法进行访问。
- Hibernate :通过持久化类的getter和setter方法或通过java的反射机制进行访问
注意:
java应用程序不能访问持久化类的private类型的getter、setter方法,而Hibernate可以。
持久化类中的属性类型可以是基本类型或包类型,他们对应相同的Hibernate映射类型。但基本类型无法表示null值,推荐使用包类型。
1.2 Hibernate访问持久化类属性的策略
通过设置映射文件中的<property>元素的access属性的方式。
- access="property"(默认),指定Hibernate通过setXXX和getXXX方法访问持久化类属性(最佳实践)。
- access="field",指定Hibernate通过java反射机制直接访问类的属性。
1.3 派生属性的映射
派生属性:持久化类的某些属性的值在运行时通过计算得出。
1)在持久化类中虽没有某个属性,表中有这个属性。
解决:在持久化类中设置该属性对应的setter和getter方法,并加入处理逻辑,然后在映射文件中映射该属性,则Hibernate就可以访问。
2)持久化类中有某个属性如avgAge,但表中没有该属性。
1.4 控制Hibernate生成的insert和update语句
HIbernate在初始化阶段,根据文件的映射信息,为所有的持久化类预定义SQL语句(insert、update、delete、select)并将其保存在SessionFactory的内置缓存中。
当session执行相应的方法时(save、update、delete、load、get),直接从缓存中调用预定义的SQL并绑定参数。
通过设置动态SQL语句提高性能, 即在持久化类的映射文件中将class的属性 dynamic-update设置成true,则Hibernate可以根据Session中保存的Monkey快照,在update时只会包含需要更新的字段。
注意:
HIbernate有两种配置文件:hibernate.properties和hibernate.cfg.xml。HIbernate默认会到classpath路径下加载hibernate.properties文件。 如果该文件不存在,则通过Configuration的configure()显示加载hibernate.cfg.xml。
2.映射对象标识符OID
2.1 对象标识符(OID)
- java语言使用内存地址来识别和区分同一个类的不同对象;
- 关系数据库按主键值来识别和区分同一个表的不同记录;
- Hibernate使用对象标识符(OID)来建立Session缓存中的对象和数据库表中记录的一一对应关系(session中对象的OID和数据库表的主键一一对应)。
2.2 主键设置自动增长
常用数据库主键设置自动增长:Mysql采用 auto_increment;MS SQL Server采用 identify ;Oracel使用序列(Sequence)中获取自动增长的标识符。
最佳实践:将持久化类的OID的setId()方法设置成private类型以防止Java应用程序随便修改OID。而将getId()设置成public使得Java应用程序可以读取持久化对象的OID。
2.3 Hibernate的内置标识符生成器
持久化类的映射文件中<generator>子元素的calss属性用来设定标识符生成器。
Hibernate的常用标识符生成器:increment、identity、sequence、hilo、native等。- increment:由Hibernate以递增的方式为代理主键赋值。在单个应用服务器上可以有效工作,不适合集群环境。
- hilo:由HIbernate按照一种high/low算法来生成标识符。不依赖于底层的数据库系统。
- identity:由底层的数据库来负责生成标识符。要求数据库把主键定义为自动增长字段类型。
- sequence:由底层的数据库提供的序列来生成标识符。要求底层的数据库系统必须支持序列。
- native:依据底层的数据库对自动生成标识符的支持能力,选择用identity、sequence或hilo标识符生成器。它能自动判断底层数据库提供的生成标识符机制。
最佳实践:使用native标识符生成器,可以跨数据库平台。
2.4 补充说明
关系数据库中的主键可以分为自然主键(具有业务含义)和代理主键(不具有业务含义),代理主键更加流行,且通常为整数类型。与此对应,在持久化类中应把OID定义为整数类型,Hibernate把OID定义为long、int或short。
3.映射一对多关联关系
说明:一对多关联与多对一关联在本节中意义等价。
在关系数据库中,只存在外键参照关系,而且总是由“many”的一方参照“one”的一方。实际上关系数据库中只存在多对一或一对一的单向关联。假设存在如下图3-1所示的关系:
图3-1 MONKEYS表参照TEAMS表
3.1 建立多对一的单向关联关系
持久化类Monkey与Team是多对一的关系,在Monkey中有一个Team类型的team属性。
public class Monkey {
...
private Team team;
...
}
Monkey通过Monkey.hbm.xml映射MONKEYS表,其中:
- name映射NAME,类型相同String类型,使用<property>映射:
<property name="name" type="string" column="NAME" /> <!--type="string"为Hibernate的映射类型-->
- team(Team类型)映射TEAM_ID(整型),类型不匹配,使用<many-to-one>映射
<many-to-one
name="team" <!--持久化类Monkey中要映射的属性team-->
column="TEAM_ID" <!--同持久化类的属性对应的表的外键TEAM_ID-->
class="mypack.Team" <!--表明team属性的类型为mypack.Team->
cascade="save-update" <!--默认为none,设置级联保存和更新-->
lazy="false" <!--立即加载策略,默认为true-->
/>
说明:cascade的值设置成save-update,可以保证当Hibernate在持久化临时对象时会自动持久化其所关联的其他临时对象。也就是说,在保存或更新Monkey对象时,会自动保存或更新与之关联的Team对象。 3.2 映射一对多双向关联
前面3.1中已经建立了Monkey端的多对一单向关联,再加上本节Team端的一对多关联,就是双向关联了。- 在Team中增加如下属性:
public class Team{
...
private Set monkeys = new HashSet();
...
}
最佳实践:在持久化类中声明接口类型的集合属性,并为他初始化为集合实现类的一个实例(可扩展、健壮性)。
- Team通过Team.hbm.xm与TEAMS映射,· 映射monkeys属性(TEAMS表中没有与其对应的字段),使用<set>
<set
name="monkeys" <!--持久化类Team中要映射的属性monkeys-->
inverse="true" <!--控制权交给Monkey-->
cascade="save-update" <!--默认为none,设置级联保存和更新-->
>
<key column="TEAM_ID" /> <!--表明关联Monkey对应的表MONKEYS的外键-->
<one-to-many class="mypack.Monkey" /> <!--表明monkeys集合中的对象为Monkey类型-->
</set>
最佳实践:在建立一对多的双向关联关系时,应该在“one”的一方把<set>元素的inverse属性设置为true,可以提高应用的性能。在建立两个对象的双向关联时,同时修改关联两端的对象的相应属性。
- 再议cascade
delete—— 级联删除,删除一个持久化对象(如Team)时,会自动删除与之关联的持久化对象(Monkey)。“删除”是指将对象由持久化状态变成删除状态。
all-delete-orphan—— 当存在父子关系时,在父方设置。说明:父子关系指由父方控制子方的持久化生命周期。如,Team删除或Team解除了与Monkey关联时,删除Monkey。
4.映射组成关系
4.1概念补充
- 组成关系:部分类的对象被多个整体类的对象共享或部分只能属于特定整体。如手属于人,电视机和录像机共用一个遥控器。
-
精粒度对象模型:对象模型(也称域模型)建立的目标是最大程度地提高代码的重用性。通过细化持久化类的粒度可提高代码可重用性,简化编程。
-
粗粒度关系数据模型:建立关系数据模型的原则是在存在数据冗余的情况下,需要把粗粒度的表拆分成具有外键参照关系的几个细粒度的表,从而节省存储空间;在没有数据冗余的前提下,应该尽可能减少表的数目,简化表之间的参照关系,以便提高访问数据库的速度。图4-1展示了对象模型与关系模型的关系:
说明:建立域模型和关系数据模型的原则不一样,使得持久化类的数目往往比数据库表的数目多,而且持久化类的属性并不和表的字段一一对应。
-
值类型与实体类型
组件类型(如Address类)就是一种值类型,它具有如下特征:
- 没有OID,在数据库中没有对应的表;
- 不能被单独持久化,其生命周期依赖于所属的持久化对象的生命周期;
- 不需要单独的映射文件;
- 其他持久化类不允许关联此组件类(Adress);(这里缺少事实说明)
- 组件类(Adress)可以关联其他的持久化类。
实体类型有OID,可以被单独持久化。
4.2 映射组成关系
Monkey使用<component>元素映射homeAddress属性,映射代码如下:
<component name="homeAddress" class="mypack.Address">
<parent name="monkey" />
<property name="province" type="string" column="HOME_PROVINCE"/>
<property name="city" type="string" column="HOME_CITY"/>
<property name="street" type="string" column="HOME_STREET"/>
<property name="zipcode" type="string" column="HOME_ZIPCODE"/>
</component>
<component>有两个属性name、class和两个子元素<parent>、<property>。
4.3 映射复合组成关系
复合组成:一个Hibernate组件包含其他Hibernate组件或者和其他的实体类关联。如图4-2所示:
图4-1 对象模型与关系模型的关系示例
其中,Computer和Vendor为实体类。
Computer.hbm.xml中的复合组成关系的映射代码如下:
<component name="cpuBox" class="mypack.CpuBox">
<parent name="computer" />
<property name="type" type="string" >
<column name="CPUBOX_TYPE" />
</property>
<component name="graphicsCard" class="mypack.GraphicsCard">
<parent name="cpuBox" />
<property name="type" type="string" >
<column name="GRAPHICSCARD_TYPE" />
</property>
</component>
<many-to-one <!--注意:这里允许组件类关联其他的持久化类-->
name="vendor"
column="CPUBOX_VENDOR_ID"
class="mypack.Vendor"
not-null="true"
/>
</component>
这里的<component>可以嵌套。5.映射继承关系
5.1 概述
有如图5-1中的对象模型:
图5-1 包含继承关系的对象模型
此对象模型的实现及其中的持久化类的实现都是一样的,但可以有不同的映射方式,也就对应着不同的关系数据模型和映射文件。
三种映射继承关系的方式:
- 继承关系树中的每个具体类对应一个表:关系数据模型完全不支持多态关联和多态查询。
- 继承关系树中的根类对应一个表:对关系数据模型进行非常规设计,在数据表中加入额外的区分子表类型的字段。这种方式使得关系数据模型支持多态关联和多态查询,并且有最佳的查询性能。但和子类的属性对应的字段要满足允许为null的要求。(个人觉得是最佳实践)
- 继承关系树的每个类对应一个表:常规设计,在关系数据模型中用外键参照关系来表示继承关系。查询性能不如第二种。
多态查询:在持久化层,利用”from Monkey“查询出所有的Monkey对象。
多态关联:在持久化层,加载的Team对象中monkeys集合中包含所有关联的Monkey对象。
注意:
以下介绍的三种方式中的Monkey类都定义为抽象类。
5.2 继承关系树中的每个具体类对应一个表
这里将Monkey定义为抽象类,没有创建MONKEYS数据表和Monkey.hbm.xml映射文件。
图5-2是每个具体类对应一个表:
图5-2 每个具体类对应一个表
图5-3是持久化类、映射文件和数据表之间的对应关系:
图5-3 持久化类、映射文件和数据表之间的对应关系
虽然Team类到Monkey类是多态关联的但关系数据库模型中没有描述Monkey和其子类的继承关系,所以无法映射Team类的Monkeys集合。这就导致:
- 不支持多态查询
为检索所有的Monkey对象应分别检索JMonkey和CMonkey,然后合并到同一集合中。
- 不支持多态关联
加载的Team对象中的monkeys集合中不包含任何的Monkey对象,需显示检索出所有的与Team对象关联的JMonkey和CMonkey对象然后加载到monkeys集合中。
- 支持多态插入
如,save(monkey)时能根据monkey变量实际引用的实例类型插入数据。
5.3 继承关系树中的根类对应一个表
图5-4中继承关系树的根类对应一个表:
图5-4 继承关系树的根类对应一个表
图5-5 是持久化类、映射文件和数据表之间的对应关系:
图5-5 持久化类、映射文件和数据表之间的对应关系
Team类到Monkey类是多态关联的且关系数据库模型中可以描述Monkey和其子类的继承关系。
Team.hbm.xml核心映射代码:
<set
name="monkeys"
inverse="true"
>
<key column="TEAM_ID" />
<one-to-many class="mypack.Monkey" />
</set>
Monkey.hbm.xml核心映射代码:
<class name="mypack.Monkey" table="MONKEYS">
<id name="id" type="long" column="ID">
<generator class="increment"/>
</id>
<discriminator column="MONKEY_TYPE" type="string" /> <!--指定MONKEYS表中用于区分Monkey类型的字段。“JM”代表JMonkey,“CM”代表CMonkey-->
<property name="name" type="string" column="NAME" />
<many-to-one
name="team"
column="TEAM_ID"
class="mypack.Team"
/>
<subclass name="mypack.JMonkey" discriminator-value="JM" >
<property name="color" column="COLOR" type="string" />
</subclass>
<subclass name="mypack.CMonkey" discriminator-value="CM" >
<property name="length" column="LENGTH" type="double" />
</subclass>
</class>
当Monkey不是抽象类时,可以如下定义calss元素:
<class name="mypack.Monkey" table="MONKEYS" discriminator-value="MM">
5.3 继承关系树的每个类对应一个表
图5-6所示 继承关系树的每个类对应一个表
图5-6 继承关系树的每个类对应一个表
图5-7是 持久化类、映射文件和数据表之间的对应关系:
图5-7 持久化类、映射文件和数据表之间的对应关系
Team.hbm.xml中的映射代码与5.2节中的相同。
Monkey.hbm.xml核心映射代码如下:
<class name="mypack.Monkey" table="MONKEYS">
<id name="id" type="long" column="ID">
<generator class="increment"/>
</id>
<property name="name" type="string" column="NAME" />
<many-to-one
name="team"
column="TEAM_ID"
class="mypack.Team"
/>
<joined-subclass name="mypack.JMonkey" table="JMONKEYS" >
<key column="MONKEY_ID" />
<property name="color" column="COLOR" type="string" />
</joined-subclass>
<joined-subclass name="mypack.CMonkey" table="CMONKEYS" >
<key column="MONKEY_ID" />
<property name="length" column="LENGTH" type="double" />
</joined-subclass>
</class>
6.映射值类型集合
值类型集合(images)中存放的对象没有OID,且他们的生命周期依赖于集合所属的对象(Monkey)的生命周期。
- java.util.Set:集合中对象无序且无重复。其实现TreeSet能对其排序。
- java.uitl.List:集合中对象按索引位置排序,且可以有重复对象。
- java.util.Map:集合中的每一个元素包含一对键对象和值对象,键对象无重复,值对象可重复。其实现TreeMap能对键对象排序。
Hibernate通过<set>、<idbag>、<list>和<map>元素可以将java集合映射到数据库。
注意:
1. <idbag>用来映射Bag集合(元素允许重复,但无特定顺序),而java中无Bag的接口,可在持久化类中用List来模拟。
2. Hibernate都提供了内置集合类封装了Java的集合类,当Session从数据库中加载Java集合时,会创建Hibernate内置集合的实例而不是java的集合实现类,这可以方便实现诸如集合代理、延迟检索、脏检查的功能。
3. 这里的集合值类型与组件类值类型有区别。
6.1 映射Set
有如图6-1的表结构:
图6-1 MONKEYS表和IMAGES表结构
这里使用联合主键确保Monkey对象不允许有重复的照片文件名。
- Monkey中的image属性:
private Set images=new HashSet();
- Monkey.hbm.xml中映射images属性:
<set name="images" table="IMAGES" lazy="true" > <!--使用了延迟加载(默认),需使用Hibernate类的initialize()显示初始化images集合-->
<key column="MONKEY_ID" /> <!--IMAGES表的外键为MONKEY_ID-->
<element column="FILENAME" type="string" not-null="true"/>
</set>
6.2 映射Bag
图6-2显示了MONKEYS和IMAGES表结构:
图6-2 MONKEYS和IMAGES表结构
Bag包中的对象允许有重复,定义一个代理主键ID。
- 用List模拟Bag,在Monkey中定义如下images属性:
private List images=new ArrayList();
- Monkey.xml中映射images属性:
<idbag name="images" table="IMAGES" lazy="true">
<collection-id type="long" column="ID">
<generator class="increment"/>
</collection-id>
<key column="MONKEY_ID" />
<element column="FILENAME" type="string" not-null="true"/>
</idbag>
6.3 映射List
图6-3显示了MONKEYS和IMAGES表结构:
图6-3 MONKEYS和IMAGES表结构
IMAGES表中多了一个位置索引字段POSITION,按位置排序(集合中元素有固定索引位置);MONKEY_ID和POSITION为联合主键,使得images集合可以存放重复对象。
- Monkey中的images属性的定义方式同6.2,但用<list>映射:
private List images=new ArrayList();
- Monkey.hbm.xml中映射images属性:
<list name="images" table="IMAGES" lazy="true">
<key column="MONKEY_ID" />
<list-index column="POSITION" /> <!--设置代表索引的POSITION字段-->
<element column="FILENAME" type="string" not-null="true"/>
</list>
6.4 映射Map
图6-4显示了MONKEYS表和IMAGES表结构:
图6-4 MONKEYS表和IMAGES表结构
这里MONKEY_ID和IMAGE_NAME作为联合组件,使得对象不能有重复的键值。
- Monkey中的images属性的定义:
private Map images=new HashMap();
- Monkey.hbm.xml中映射images属性:
<map name="images" table="IMAGES" lazy="true">
<key column="MONKEY_ID" />
<map-key column="IMAGE_NAME" type="string"/>
<element column="FILENAME" type="string" not-null="true"/>
</map>
6.5 对集合排序
Hibernate对集合中的元素两种排序方式:- 数据库排序:Hibernate通过select到数据库中检索集合对象是,利用order by子句进行排序。
- 内存排序:Hibernate把数据库中集合数据加载到内存中的Java集合后,利用Java的自然排序或客户化排序方式排序。
在映射文件中,Hibernate用sort属性设置内存排序,用order-by设置数据库排序。
图6-5显示了<set>、<idbag>、<list>、<map>的排序属性:
图6-5 <set>、<idbag>、<list>、<map>的排序属性
7.映射一对一关联关系
在映射组成关系时我们讨论了Monkey和Address类的组成关系,下面我们采用一对一的关联映射,当然如果从头设计对象模型和数据模型应优先考虑组成关系。映射一对一关系两种方式:- 按照外键映射:在MONKEYS表中定义两个外键HOME_ADDRESS_ID和COM_ADDRESS_ID,他们都参照ADDRESS表的主键。缺点:只能建立一个双向一对一关联,而另一个为单向一对一关联。
- 按照主键映射:ADDRESS表的ID既是主键又是外键,参照MONKEYS表的主键。缺点:只有一个一对一关联,应优先考虑使用主键映射方式。
7.1 按照外键映射
如图7-1表关系:
图7-1 MONKEYS与ADDRESSES表结构
- Monkey类中的homeAddress属性和comAddress属性定义:
private Address homeAddress;
private Address comAddress;
- Address中的monkey属性定义:
private Monkey monkey;
- Monkey.hbm.xml中映射homeAddress和comAddress属性:
<many-to-one name="homeAddress"
class="mypack.Address"
column="HOME_ADDRESS_ID"
cascade="all" <!--"all"表明保存更新或删除Monkey对象是会级联保存、更新、删除homeAddress-->
unique="true" <!--表明Monkey对象有唯一的一个homeAddress对象-->
/>
<many-to-one name="comAddress"
class="mypack.Address"
column="COM_ADDRESS_ID"
cascade="all"
unique="true"
/>
- Address.hbm.xm中映射Monkey:
<one-to-one name="monkey"
class="mypack.Monkey"
property-ref="homeAddress" <!--表明建立homeAddress到Monkey对象的关联-->
/>
这里建立了Monkey和homeAddress对象之间的双向关联,而只有Monkey到comAddress的单向关联。(解决:把Address类定义为抽象类,HomeAddress和ComAddress为其子类,在HomeAddress.hbm.xml和ComAddress.hbm.xml中用<one-to-one>映射各自的属性monkey。但复杂对象模型变得复杂....)7.2 按主键映射
假设Monkey类中只有一个address属性,如图7-2表结构:
图7-2 MONKEYS表和ADDRESSES表结构
MONKEYS表与ADDRESSES表共享主键。
- Monkey.hbm.xml中映射address属性:
<one-to-one name="address"
class="mypack.Address"
cascade="all"
/>
- Address.hbm.xml映射monkey属性:
<class name="mypack.Address" table="ADDRESSES" >
<id name="id" type="long" column="ID">
<generator class="foreign"> <!--OID使用foreign生成策略保证Address对象与Monkey对象共享同一个OID-->
<param name="property">monkey</param>
</generator>
</id>
.......
<one-to-one name="monkey"
class="mypack.Monkey"
constrained="true" <!--ADDRESSES表的ID主键同时作为外键参照MONKEYS表-->
/>
8.映射多对多关联关系
8.1 映射单向多对多关联关系
如图8-1表关系:
图8-1 MONKEYS、TEACHERS及连接表的结构
建立Monkey到Teacher的单向多对多关系:
- Monkey中的teachers属性定义:
private Set teachers=new HashSet();
- Monkey.hbm.xml映射teachers属性:
<set name="teachers" table="LEARNING"
lazy="true"
cascade="save-update"> <!--多对多应将cascade属性设置成“save-update”-->
<key column="MONKEY_ID" />
<many-to-many class="mypack.Teacher" column="TEACHER_ID" />
</set>
8.2 映射双向多对多关联关系
Monkey类与Teacher三种映射方式实现多对多关联:
- 两端都用<set>,其中一端的inverse属性为true。
- 定义专门的组件类Learning来描述关系,适合关联包含属性的情形。
- 分解多对多关系为Monkey与Learning,及Teacher与Learning类的两个一对多关系。(最佳实践:可以使对象模型和关系模型具有更好的可扩展性)
8.2.1 关联两端使用<set>
- Monkey类中定义teachers属性:
private Set teachers=new HashSet();
- Teacher类中定义monkeys属性:
private Set monkeys=new HashSet();
- Monkey.hbm.xml映射teachers属性:
<set name="teachers" table="LEARNING"
lazy="true"
cascade="save-update">
<key column="MONKEY_ID" />
<many-to-many class="mypack.Teacher" column="TEACHER_ID" />
</set>
- Teacher.hbm.xml映射monkeys属性:
<set name="monkeys" table="LEARNING"
lazy="true"
inverse="true"
cascade="save-update">
<key column="TEACHER_ID" />
<many-to-many class="mypack.Monkey" column="MONKEY_ID" />
</set>
8.2.2 使用组件类集合
如图8-2表结构:
图8-2 MONKEYS、TEACHERS及连接表的结构
首先编写组件类Learning。
- Monkey类和Teacher都定义了Set类型的learnings属性:
private Set learnings=new HashSet();
- Monkey.hbm.xml映射learnings:
<set name="learnings" lazy="true" table="LEARNING" >
<key column="MONKEY_ID" />
<composite-element class="mypack.Learning" >
<parent name="monkey" />
<many-to-one name="teacher" class="mypack.Teacher" column="TEACHER_ID" not-null="true"/>
<property name="gongfu" column="GONGFU" type="string" not-null="true" />
</composite-element>
</set>
- Teacher.hbm.xml映射learnings:
<set name="learnings" lazy="true" inverse="true" table="LEARNING" >
<key column="TEACHER_ID" />
<composite-element class="mypack.Learning" >
<parent name="teacher" />
<many-to-one name="monkey" class="mypack.Monkey" column="MONKEY_ID" not-null="true"/>
<property name="gongfu" column="GONGFU" type="string" not-null="true" />
</composite-element>
</set>
8.2.3 把多对一关联分解为两个一对多关联
如图8-3表结构:
图8-3 MONKEYS、TEACHERS及连接表的结构
这里Learning是实体类。
- Monkey类和Teacher都定义了Set类型的learnings属性:
private Set learnings=new HashSet();
- Learning定义了monkey和teacher属性:
private Teacher teacher;
private Monkey monkey;
- Monkey.hbm.xml映射learnings:
<set name="learnings" lazy="true" inverse="true" cascade="save-update">
<key column="MONKEY_ID" />
<one-to-many class="mypack.Learning" />
</set>
- Teacher.hbm.xml映射learnings:
<set name="learnings" lazy="true" inverse="true" cascade="save-update">
<key column="TEACHER_ID" />
<one-to-many class="mypack.Learning" />
</set>
- Learning.hbm.xml映射monkey和teacher属性:
<class name="mypack.Learning" table="LEARNING" >
<id name="id" type="long" column="ID">
<generator class="increment"/>
</id>
<property name="gongfu" column="GONGFU" type="string" />
<many-to-one name="monkey" column="MONKEY_ID" class="mypack.Monkey" not-null="true" />
<many-to-one name="teacher" column="TEACHER_ID" class="mypack.Teacher" not-null="true" />
</class>
<这是测试目录生成的BUG>
9.总结
处理映射关系从四个方面把握:
- 在持久化类中体现出雷雨类之间的特定关系;
- 数据表与持久化类对应;
- 创建对象-关系映射文件;
- 通过Hibernate API操纵具有特定关系的多个对象。