zoukankan      html  css  js  c++  java
  • 转: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 {
    private int id;
    private String name;
    private Set students;

    ...//生成相应的getter、setter方法

    }

    ---------------------------------------------------------------------------

    public class Student {
    private int id;
    private String name;

    ..//生成相应是getter、setter方法

    }

    **映射原理:一对多关联映射,在多的一端添加一个外键指向一的一端,它维护的关系是一指向多

    **配置文件:

    <class name="Classes" table="t_classes">
       <id name="id">
        <generator class="native"/>
       </id>
       <property name="name"/>
       <set name="students">
        <key column="classesid"/>//在一的一端添加的外键指向多的一端(默认情况下市主键匹配)
        <one-to-many class="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">
       <id name="id">
        <generator class="native"/>
       </id>
       <property name="name"/>
       <set name="students">
        <key column="classesid"/>

        <many-to-many class="xxx.Student" unique="true"/>
       </set>
    </class>

    五、单向多对多

    **先看两个POJO

    public class User {
    private int id;
    private String name;
    private Set roles;

    ..//生成相应的getter、setter方法

    }

    ---------------------------------------------------------------------------

    public class Role {
    private int id;
    private String name;

    ..//生成相应的getter、setter方法

    }

    现在需要映射这样的N-N关系,一个User可以有多个Role,而一个Role有可以被多个User所拥有

    这样我们就可以将一个N-N关系拆分为两个N-1的关系

    **看配置文件

    <class name="xxx.User" table="t_user">
       <id name="id">
        <generator class="native"/>
       </id>
       <property name="name"/>
       <set name="roles" table="t_user_role">
        <key column="userid"/>
        <many-to-many class="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 {
    private int id;
    private String name;

    privarte Set user

    ..//生成相应的getter、setter方法

    }

    修改配置文件

    <class name="xxx.User" table="t_user">
       <id name="id">
        <generator class="native"/>
       </id>
       <property name="name"/>
       <set name="roles" table="t_user_role">
        <key column="userid"/>
        <many-to-many class="xxx.Role" column="roleid"/>
       </set>
    </class>

    ------------------------------------------------------------------------------------------------

    <class name="xxx.Role" table="t_role">
       <id name="id">
        <generator class="native"/>
       </id>
       <property name="name"/>
       <set name="users" table="t_user_role" order-by="userid">
        <key column="roleid"/>
        <many-to-many class="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;
    private String name;
    private IdentityId identityId;

    ..//生成相应的getter、setter方法

    }

    public class IdentityId {
    private int id;
    private String cardNo;
    private Person person;

    ..//生成相应的getter、setter方法

    }

    **看配置文件

    <class name="xxx.Person" table="t_person">
       <id name="id">
        <generator class="native"/>
       </id>
       <property name="name"/>
       <many-to-one name="identityId" class="xxx.IdentityId" unique="true"/>
    </class>

    -----------------------------------------------------------------------------------

    <class name="xxx.IdentityId" table="t_identity">
       <id name="id">
        <generator class="native"/>
       </id>
       <property name="cardNo"/>
       <one-to-one name="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">
       <id name="id" column="ID">
        <generator class="foreign">
         <param name="property">identityId</param>
        </generator>
       </id>
       <property name="name"/>
       <one-to-one name="identity" clsss="xxx.IdentityId" constrained="true"/>
    </class>

    注意:这里的constrained="true"表明Person表的主键ID同时作为外键参考IdentityId表

    --------------------------------------------------------------------------------------

    <class name="xxx.Identity" table="t_identity">
       <id name="id">
        <generator class="native"/>
       </id>
       <property name="cardNo"/>
       <one-to-one name="person" class="xxx.Person"/>
    </class>

    注意:这里Person表中ID既是主键同时还作为外键参照表IdentityId,因为使用了foreign标识符生成策略Hibernate就保证了Person

    对象与关联的IdentityId对象共享一个主键

    综上所述,hibernate的实体映射方式很灵活,如果我们使用hibernate映射得当将可以大大简化持久层数据的访问!

    
  • 相关阅读:
    Basic and Digest Access Authentication 及HttpClient实现
    SQL Server2000 解析XML
    ashx+jQuery,一个轻量级的asp.net ajax解决方案
    sql 获取整时 整分秒 数据
    无法使用前导.. 在顶级目录上退出
    sql查询分析器调用自定义函数
    SqlServer 重置自动编号起始值
    asp.net不使用ViewState和服务器控件
    解决 "错误7405:异类查询要求为连接设置ANSI_NULLS和ANSI_WARNINGS
    ASP.NET服务器控件几乎都有的成员
  • 原文地址:https://www.cnblogs.com/phoebus0501/p/1964114.html
Copyright © 2011-2022 走看看