Hibernate之关系映射
在关系型数据库存在着4种关系映射:多对一、一对多、一对一、多对多,下面依次对这四种关系如何在关系模型和对象模型中实现加以说明。
【多对一】
比如有Employee类和Department类,其中employee相对于department来说就是多对一,因为多个employee可以属于同一个department.
在关系模型中要实现这种映射需要在t_employee表中加一列departmentId,外键约束为t_department的主键id上。
而在对象模型中,只需要让Employee类中有一个department的属性.
要想在hibernate中映射这种关系,需要在多的一方,这里就是Employeed.hbm.xml中使用<many-to-one>标签。
<many-to-one name="department" column="departmentId" class="Department" cascade="all" outer-join="true"/>
其中column属性指定用t_emplyee表中的哪一列去匹配t_department表的主键
class属性指定用什么类去映射t_department表
cascade属性表示当employee对象save,update 或者 delete的时候,是否需要对department进行相应的操作
outer-join属性:当查询t_employee表时,hibernate默认是先查询出employee的departmentId,然后根据这个departmentId去t_department中查询对应的department,但当outer-join设置为true时,hibernate会采用表连接的方式同时将两张表中的数据查询出来。
【一对多】
还是上面的employee和department的例子,department相对于employee就是一对多的关系,因为一个department可以有多个employee.
这种关系在关系模型下的实现和多对一是一样的,还是在【多】的一方建立一个外键,关联到【一】的主键上。
但对象模型需要修改下,需要在【一】的属性中加一个集合属性,用来存放与之对应的【多】对象,在这个例子就是要在Department类中加一个List<Employee> employees.
而Hibernate中要想实现这种映射,需要在Department.hbm.xml中使用<set>标签
<set name="employees" table="t_employee" cascade="all">
<key column="departmentId"/>
<one-to-many class="Department"/>
</set>
无论是设置<many-to-one>的column属性还是<set>标签的子元素标签<key>,只要记住,hibernate需要知道用【多】这一方的哪一列去和【一】的主键匹配,所以要提供外键的列明。
【双向映射】
上面讲的无论是多对一还是一对多都是单向的,只能通过employee找到department,或者只能通过department找到employee,要想实现双向的也很简单,只要同时在【多】的一方使用<many-to-one>,还要在【一】的一方使用<set>就行了,但这里有个问题要注意,在使用双向映射的时候,要把关系维持的控制权给多的一方,不然hibernate会发insert语句,然后发update语句,可以形象的比喻,是公司的老板记住所有员工的名字快,还是让所有员工记住老板的名字快?如何把控制权给【多】的一方呢,就是在一的一方的<set/>设置inverse属性为true.
【一对一】
employee和idCard就是这种关系,一个employee只可能有一个idCard,一个idCard也只可能对应一个employee,其中employee叫主对象,idCard叫从对象,因为没有了employee,idCard是没有意义的。
在关系模型中有两种方法实现这种关系,但在对象模型中,只要互相持有对方的引用即可,下面分别将如何在关系模型中实现这种关系,以及hibernate如何映射。
一、主键关联
即让从对象的主键和主对象的主键一样。
在主对象employee.hbm.xml中使用<one-to-one>标签
<one-to-one name="idCard" class="IdCard" cascade="all"/>
不用指定column属性,因为hibernate知道用两张表的主键去匹配
在从对象idCard.hbm.xmlo中同样也要使用<one-to-one>标签
<one-to-one name="employee" class="Employee" constrained="true"/>
因为idCard的主键是根据employee的主键而来的,所以特别配置主键的生成策略
<id name="id" column="id">
<generator class="foreign">
<param name="property">user</param>
</generator>
</id>
在IdCard的id主鍵上,使用foreign表示與外鍵共享主鍵,也就是與Employee實體共享主鍵,而constrained設定為true,表示約束
idCard的主鍵必須與employee中對應資料的主鍵相同。
二、唯一外键关联
这种方式关系模型实际就是多对一,但加了一个约束,要求外键不能重复
加入unique="true"即可完成单向的一对一:
<many-to-one name="department"
column="departmentId"
class="Department"
cascade="all"
outer-join="true"
unique="true"/>
如果想要实现双向的一对一,需要在department.hbm.xml也加入<one-to-one>
<one-to-one name="employee"
class="onlyfun.caterpillar.User"
property-ref="deparment"/>
在关系型数据库存在着4种关系映射:多对一、一对多、一对一、多对多,下面依次对这四种关系如何在关系模型和对象模型中实现加以说明。
【多对一】
比如有Employee类和Department类,其中employee相对于department来说就是多对一,因为多个employee可以属于同一个department.
在关系模型中要实现这种映射需要在t_employee表中加一列departmentId,外键约束为t_department的主键id上。
而在对象模型中,只需要让Employee类中有一个department的属性.
要想在hibernate中映射这种关系,需要在多的一方,这里就是Employeed.hbm.xml中使用<many-to-one>标签。
<many-to-one name="department" column="departmentId" class="Department" cascade="all" outer-join="true"/>
其中column属性指定用t_emplyee表中的哪一列去匹配t_department表的主键
class属性指定用什么类去映射t_department表
cascade属性表示当employee对象save,update 或者 delete的时候,是否需要对department进行相应的操作
outer-join属性:当查询t_employee表时,hibernate默认是先查询出employee的departmentId,然后根据这个departmentId去t_department中查询对应的department,但当outer-join设置为true时,hibernate会采用表连接的方式同时将两张表中的数据查询出来。
【一对多】
还是上面的employee和department的例子,department相对于employee就是一对多的关系,因为一个department可以有多个employee.
这种关系在关系模型下的实现和多对一是一样的,还是在【多】的一方建立一个外键,关联到【一】的主键上。
但对象模型需要修改下,需要在【一】的属性中加一个集合属性,用来存放与之对应的【多】对象,在这个例子就是要在Department类中加一个List<Employee> employees.
而Hibernate中要想实现这种映射,需要在Department.hbm.xml中使用<set>标签
<set name="employees" table="t_employee" cascade="all">
<key column="departmentId"/>
<one-to-many class="Department"/>
</set>
无论是设置<many-to-one>的column属性还是<set>标签的子元素标签<key>,只要记住,hibernate需要知道用【多】这一方的哪一列去和【一】的主键匹配,所以要提供外键的列明。
【双向映射】
上面讲的无论是多对一还是一对多都是单向的,只能通过employee找到department,或者只能通过department找到employee,要想实现双向的也很简单,只要同时在【多】的一方使用<many-to-one>,还要在【一】的一方使用<set>就行了,但这里有个问题要注意,在使用双向映射的时候,要把关系维持的控制权给多的一方,不然hibernate会发insert语句,然后发update语句,可以形象的比喻,是公司的老板记住所有员工的名字快,还是让所有员工记住老板的名字快?如何把控制权给【多】的一方呢,就是在一的一方的<set/>设置inverse属性为true.
【一对一】
employee和idCard就是这种关系,一个employee只可能有一个idCard,一个idCard也只可能对应一个employee,其中employee叫主对象,idCard叫从对象,因为没有了employee,idCard是没有意义的。
在关系模型中有两种方法实现这种关系,但在对象模型中,只要互相持有对方的引用即可,下面分别将如何在关系模型中实现这种关系,以及hibernate如何映射。
一、主键关联
即让从对象的主键和主对象的主键一样。
在主对象employee.hbm.xml中使用<one-to-one>标签
<one-to-one name="idCard" class="IdCard" cascade="all"/>
不用指定column属性,因为hibernate知道用两张表的主键去匹配
在从对象idCard.hbm.xmlo中同样也要使用<one-to-one>标签
<one-to-one name="employee" class="Employee" constrained="true"/>
因为idCard的主键是根据employee的主键而来的,所以特别配置主键的生成策略
<id name="id" column="id">
<generator class="foreign">
<param name="property">user</param>
</generator>
</id>
在IdCard的id主鍵上,使用foreign表示與外鍵共享主鍵,也就是與Employee實體共享主鍵,而constrained設定為true,表示約束
idCard的主鍵必須與employee中對應資料的主鍵相同。
二、唯一外键关联
这种方式关系模型实际就是多对一,但加了一个约束,要求外键不能重复
加入unique="true"即可完成单向的一对一:
<many-to-one name="department"
column="departmentId"
class="Department"
cascade="all"
outer-join="true"
unique="true"/>
如果想要实现双向的一对一,需要在department.hbm.xml也加入<one-to-one>
<one-to-one name="employee"
class="onlyfun.caterpillar.User"
property-ref="deparment"/>