HIBERNATE关联关系映射
1、单向N-1
2、单向1-1
3、单向1-N
4、单向N-N
5、双向1-N
6、双向N-N
7、双向1-1
下面就对这七种关联关系映射进行一个简单的总结:
一、单向的多对一
看两个POJO
public class Person{
private int pid;
private String name;
private Address address;
...//生成相应的getter、setter方法
}
----------------------------------------
public class Address{
private int id;
private String detail;
...//生成相应的getter、setter方法
}
这里我们需要维护的关系是多个Person可以对应同一个地址,使用单向的N-1映射我们只需要在多的一端加入一个外键指向一的一端即可
**看配置文件
<class name="Person">
<id name="id">
<generator class="native"/>
</id>
...//部分字段配置省略
<many-to-one name="address" column="addressId"/>//关键配置
</class>
这样配置以后hibernate就会帮我们在多的一端(Person)添加一个外键addressId指向一的一端
二、单向的1-1(外键关联)
可以采用<many-to-one>标签,指定多的一端的unique=true,这样就限制了多的一端的多重性唯一
通过这种手段映射一对一唯一外键关联
配置文件只需要修改为:
<many-to-one name="address" column="addressId" unique="true"/>
三、单向的1-N
**看代码,我们知道一个班级有多名学生,这就是一个典型的1-N关系
public class Classes {
privateintid;
privateStringname;
private Set students;...//生成相应的getter、setter方法
}
---------------------------------------------------------------------------
public class Student {
privateintid;
private String name;..//生成相应是getter、setter方法
}
**映射原理:一对多关联映射,在多的一端添加一个外键指向一的一端,它维护的关系是一指向多
**配置文件:
<class name="Classes" table="t_classes">
<idname="id">
<generatorclass="native"/>
</id>
<propertyname="name"/>
<setname="students">
<keycolumn="classesid"/>//在一的一端添加的外键指向多的一端(默认情况下市主键匹配)
<one-to-manyclass="xxx.Student"/>//注意它维护的是一指向多的关系
</set>
</class>四、双向1-N
上面提到了单向的1-N在一的一端添加的外键指向多的一端即可,对于双向的1-N则类似于N-N,集合元素中不使用<one-to-many>
元素映射关联属性,而使用<many-to-many>元素,但是为了保证一的一端,因此需要增加unique="true"属性
**配置,简单修改单向1-N的配置文件
<class name="xxx.Classes" table="t_classes">
<idname="id">
<generatorclass="native"/>
</id>
<propertyname="name"/>
<setname="students">
<key column="classesid"/><many-to-many class="xxx.Student" unique="true"/>
</set>
</class>五、单向多对多
**先看两个POJO
public class User {
privateintid;
privateStringname;
private Set roles;..//生成相应的getter、setter方法
}
---------------------------------------------------------------------------
public class Role {
privateintid;
private String name;..//生成相应的getter、setter方法
}
现在需要映射这样的N-N关系,一个User可以有多个Role,而一个Role有可以被多个User所拥有
这样我们就可以将一个N-N关系拆分为两个N-1的关系
**看配置文件
<class name="xxx.User" table="t_user">
<idname="id">
<generatorclass="native"/>
</id>
<propertyname="name"/>
<setname="roles"table="t_user_role">
<keycolumn="userid"/>
<many-to-manyclass="xxx.Role"column="roleid"/>
</set>
</class>这样我们的关系的明确了
t_user t_user_role t_role
id name < -------userid roleid ----- > id name
六、双向的多对多关系
双向的多对多映射需要在两边都增加集合元素,用于映射集合属性
修改上面的单向N-N映射
在Role中添加集合属性
public class Role {
privateintid;
private String name;privarte Set user
..//生成相应的getter、setter方法
}
修改配置文件
<class name="xxx.User" table="t_user">
<idname="id">
<generatorclass="native"/>
</id>
<propertyname="name"/>
<setname="roles"table="t_user_role">
<keycolumn="userid"/>
<many-to-manyclass="xxx.Role"column="roleid"/>
</set>
</class>------------------------------------------------------------------------------------------------
<class name="xxx.Role" table="t_role">
<idname="id">
<generatorclass="native"/>
</id>
<propertyname="name"/>
<setname="users"table="t_user_role"order-by="userid">
<keycolumn="roleid"/>
<many-to-manyclass="xxx.User"column="userid"/>
</set>
</class>注意点:1、双向多对多关联两边都需要指定连接表的表名和外键列的列名
2、两个集合元素Set的table值必须指定,而且需要相同
七、双向的一对一关联
双向的1-1关联有两种形式:
1、基于外键的双向1-1关联
我们可以回想一下上面提到的单向1-1映射,它是有N-1的一个特例,只需要在<many-to-one>标签多的一端添加unique="true"属性就可以形成单向的1-1映射关系,那么该怎么样将这种映射改为双向的呢?
下面我们再举个例子:一个User必须要有一个唯一的identityId
首先创建两个POJO类
public class Person {
private int id;
privateStringname;
private IdentityId identityId;..//生成相应的getter、setter方法
}
public class IdentityId {
privateintid;
privateStringcardNo;
private Person person;..//生成相应的getter、setter方法
}
**看配置文件
<class name="xxx.Person" table="t_person">
<idname="id">
<generatorclass="native"/>
</id>
<propertyname="name"/>
<many-to-onename="identityId"class="xxx.IdentityId"unique="true"/>
</class>-----------------------------------------------------------------------------------
<class name="xxx.IdentityId" table="t_identity">
<idname="id">
<generatorclass="native"/>
</id>
<propertyname="cardNo"/>
<one-to-onename="person"class="xxx.Person"property-ref="identityId"/>
</class>注意:这里的property-ref属性为identity表明建立了从identity对象到person对象的关联.
因此只要调用identity持久化对象的getIdentityId()方法就可以导航到Person对象 由此可见:
Person对象和IdentityId对象之间为双向的关联关系person.getIdentityId().getPerson()
2、基于主键的1-1双向关联
上面的POJO类不需要有任何变化,我们只需要修改配置文件
<class name="xxx.Person" table="t_person">
<idname="id"column="ID">
<generatorclass="foreign">
<paramname="property">identityId</param>
</generator>
</id>
<propertyname="name"/>
<one-to-onename="identity"clsss="xxx.IdentityId"constrained="true"/>
</class>注意:这里的constrained="true"表明Person表的主键ID同时作为外键参考IdentityId表
--------------------------------------------------------------------------------------
<class name="xxx.Identity" table="t_identity">
<idname="id">
<generatorclass="native"/>
</id>
<propertyname="cardNo"/>
<one-to-onename="person"class="xxx.Person"/>
</class>注意:这里Person表中ID既是主键同时还作为外键参照表IdentityId,因为使用了foreign标识符生成策略Hibernate就保证了Person
对象与关联的IdentityId对象共享一个主键
综上所述,hibernate的实体映射方式很灵活,如果我们使用hibernate映射得当将可以大大简化持久层数据的访问!