zoukankan      html  css  js  c++  java
  • Hibernate关联映射(转载)

    原文:http://www.cnblogs.com/huxi/archive/2009/12/15/1624988.html

    以简单的两个类为例: 
    User(int id, String name) 
    Group(int id, String name)

    没有关联关系时的关系模型: 
    t_user(id int pk, name varchar) 
    t_group(id int pk, name varchar)

    一、多对一和一对多关联映射(多个用户有相同的组)

    这几种关联映射后的关系模型是相同的: 
    t_user(id int pk, name varchar, gid int fk->t_group(id)
    t_group(id int pk, name varchar)

    1、多对一单向关联

    实体模型: 
    bean.User(int id, String name, Group group
    bean.Group(int id, String name)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <!-- bean/User.hbm.xml -->
     
    <hibernate-mapping>
        <class name="bean.User" table="t_user">
            <id name="id"><generator class="native"/></id>
            <property name="name"/>
            <!-- 使用<many-to-one>映射多对一关系。导出ddl时将自动生成一个外键 -->
            <many-to-one name="group" column="gid"/>
        </class>
    </hibernate-mapping>
    1
    2
    3
    4
    5
    6
    7
    8
    <!-- bean/Group.hbm.xml -->
     
    <hibernate-mapping>
        <class name="bean.Group" table="t_group">
            <id name="id"><generator class="native"/></id>
            <property name="name"/>
        </class>
    </hibernate-mapping>
    2、一对多单向关联(几乎不用)

    实体模型: 
    bean.User(int id, String name) 
    bean.Group(int id, String name, Set users)

    1
    2
    3
    4
    5
    6
    7
    8
    <!-- bean/User.hbm.xml -->
     
    <hibernate-mapping>
        <class name="bean.User" table="t_user">
            <id name="id"><generator class="native"/></id>
            <property name="name"/>
        </class>
    </hibernate-mapping>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <!-- bean/Group.hbm.xml -->
     
    <hibernate-mapping>
        <class name="bean.Group" table="t_group">
            <id name="id"><generator class="native"/></id>
            <property name="name"/>
            <!-- 使用<set>映射集合 -->
            <set name="users">
                <!-- 使用<key>指定引用至自身的外键表(t_user)中的外键 -->
                <key column="gid"/>
                <!-- 使用<one-to-many>映射一对多关系 -->
                <one-to-many class="bean.User"/>
            </set>
        </class>
    </hibernate-mapping>

    为Group加入集合也可以使用List(<list>),注意不能指定类型是具体的HashSet或ArrayList,只能是接口Set或List。 
    集合标签可以使用order-by属性指定排序:

    1
    <set name="users" order-by="id desc">
    3、双向关联

    实体模型: 
    bean.User(int id, String name, Group group
    bean.Group(int id, String name, Set users)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <!-- bean/User.hbm.xml -->
     
    <hibernate-mapping>
        <class name="bean.User" table="t_user">
            <id name="id"><generator class="native"/></id>
            <property name="name"/>
            <!-- 使用<many-to-one>映射多对一关系。导出ddl时将自动生成一个外键 -->
            <many-to-one name="group" column="gid"/>
        </class>
    </hibernate-mapping>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <!-- bean/Group.hbm.xml -->
     
    <hibernate-mapping>
        <class name="bean.Group" table="t_group">
            <id name="id"><generator class="native"/></id>
            <property name="name"/>
            <!-- 使用<set>映射集合 -->
            <set name="users">
                <!-- 使用<key>指定引用至自身的外键表(t_user)中的外键 -->
                <key column="gid"/>
                <!-- 使用<one-to-many>映射一对多关系 -->
                <one-to-many class="bean.User"/>
            </set>
        </class>
    </hibernate-mapping>

    双向关联中,为<set>加入”inverse=true”可以反转维护关系:Hibernate将放弃从一的一端维护。意思就是user和group的关系必须使用user维护,操作group时Hibernate将不维护这个关系。

    1
    <set name="users" inverse="true">

    操作group的示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    session.beginTransaction();
    User user = new User();
    user.setName("张三");
     
    Group group = new Group();
    group.setName("admin");
    group.setUsers(new HashSet());
    group.getUsers().add(user);
     
    session.save(user);
    session.save(group);
    session.getTransaction().commit();

    没有配置inverse=”true”时,Hibernate输出了添加user和group,并更新user的语句:

    Hibernate: insert into t_user (name, gid) values (?, ?)
    Hibernate: insert into t_group (name) values (?)
    Hibernate: update t_user set gid=? where id=?
    而配置了inverse=”true”后,Hibernate仅仅输出了添加user和group的语句,并没有更新user,放弃了关系的维护:
    Hibernate: insert into t_user (name, gid) values (?, ?)
    Hibernate: insert into t_group (name) values (?)
    此时应该从user端维护关系:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    session.beginTransaction();
    Group group = new Group();
    group.setName("admin");
     
    User user = new User();
    user.setName("张三");
    user.setGroup(group);
     
    session.save(group);
    session.save(user);
    session.getTransaction().commit();

    因为外键列在t_user表中,从group端维护需要操作多表,所以从user端维护关系更加合理,效率也更高。上面的代码输出两条SQL语句,插入数据的同时也维护了关系:

    Hibernate: insert into t_group (name) values (?)
    Hibernate: insert into t_user (name, gid) values (?, ?)

    二、一对一关联映射(每个用户独有一个组)

    依照映射方法不同,可分为主键关联映射唯一外键关联映射。主键关联是维护两张表的主键一致,如有必要还可以在主键上再加上外键约束;唯一外键关联则类似于多对一关联,为表加入一个外键列,不过一对一关联会同时将这个外键加上唯一约束。

    1、主键关联映射

    主键关联生成的关系模型: 
    t_user(id int pk fk->t_group(id), name varchar) 
    t_group(id int pk, name varchar)

    1.1、主键单向关联

    实体模型: 
    bean.User(int id, String name, Group group
    bean.Group(int id, String name)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <!-- bean/User.hbm.xml -->
     
    <hibernate-mapping>
        <class name="bean.User" table="t_user">
            <id name="id">
                <!-- 指定主键生成策略为外键 -->
                <generator class="foreign">
                    <!-- 指定要参照的属性 -->
                    <param name="property">group</param>
                </generator>
            </id>
            <property name="name"/>
            <!-- 使用<one-to-one>映射一对一关系。 -->
            <one-to-one name="group">
        </class>
    </hibernate-mapping>
    1
    2
    3
    4
    5
    6
    7
    8
    <!-- bean/Group.hbm.xml -->
     
    <hibernate-mapping>
        <class name="bean.Group" table="t_group">
            <id name="id"><generator class="native"/></id>
            <property name="name"/>
        </class>
    </hibernate-mapping>

    主键关联由Hibernate维护,不依赖数据库。如果需要在数据库端也生成外键约束,可以使用constrained:

    1
    <one-to-one name="group" constrained="true"/>

    1.2、主键双向关联

    实体模型: 
    bean.User(int id, String name, Group group
    bean.Group(int id, String name, User user)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <!-- bean/User.hbm.xml -->
     
    <hibernate-mapping>
        <class name="bean.User" table="t_user">
            <id name="id">
                <!-- 指定主键生成策略为外键 -->
                <generator class="foreign">
                    <!-- 指定要参照的属性 -->
                    <param name="property">group</param>
                </generator>
            </id>
            <property name="name"/>
            <!-- 使用<one-to-one>映射一对一关系。 -->
            <one-to-one name="group">
        </class>
    </hibernate-mapping>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <!-- bean/Group.hbm.xml -->
     
    <hibernate-mapping>
        <class name="bean.Group" table="t_group">
            <id name="id"><generator class="native"/></id>
            <property name="name"/>
            <!-- 使用<one-to-one>映射一对一关系 -->
            <one-to-one name="user"/>
        </class>
    </hibernate-mapping>
    2、唯一外键关联映射

    唯一外键关联生成的关系模型: 
    t_user(id int pk, name varchar, gid int fk->t_group(id)
    t_group(id int pk, name varchar)

    2.1、唯一外键单向关联

    实体模型: 
    bean.User(int id, String name, Group group
    bean.Group(int id, String name)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <!-- bean/User.hbm.xml -->
     
    <hibernate-mapping>
        <class name="bean.User" table="t_user">
            <id name="id">
                <generator class="native"/>
            </id>
            <property name="name"/>
            <!-- 为<many-to-one>加上unique就变成了一对一 -->
            <many-to-one name="group" unique="true" column="gid"/>
        </class>
    </hibernate-mapping>
    1
    2
    3
    4
    5
    6
    7
    8
    <!-- bean/Group.hbm.xml -->
     
    <hibernate-mapping>
        <class name="bean.Group" table="t_group">
            <id name="id"><generator class="native"/></id>
            <property name="name"/>
        </class>
    </hibernate-mapping>

    2.2、唯一外键双向关联

    实体模型: 
    bean.User(int id, String name, Group group
    bean.Group(int id, String name, User user)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <!-- bean/User.hbm.xml -->
     
    <hibernate-mapping>
        <class name="bean.User" table="t_user">
            <id name="id">
                <generator class="native"/>
            </id>
            <property name="name"/>
            <!-- 为<many-to-one>加上unique就变成了一对一 -->
            <many-to-one name="group" unique="true" column="gid"/>
        </class>
    </hibernate-mapping>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <!-- bean/Group.hbm.xml -->
     
    <hibernate-mapping>
        <class name="bean.Group" table="t_group">
            <id name="id"><generator class="native"/></id>
            <property name="name"/>
            <!-- 使用<one-to-one>映射一对一 -->
            <one-to-one name="user"/>
        </class>
    </hibernate-mapping>

    三、多对多关联映射(每个用户拥有多个组,每个组也有多个用户)

    多对多关联映射关系使用中间表表示。导出关系模型时Hibernate将自动生成复合主键以及外键约束。

    关系模型: 
    t_user(id int pk, name varchar) 
    t_group(id int pk, name varchar) 
    t_user_group(userid int fk->t_user(id), groupid int fk->t_group(id)pk(userid, groupid))

    1、多对多单向关联

    实体模型: 
    bean.User(int id, String name, Set groups
    bean.Group(int id, String name)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <!-- bean/User.hbm.xml -->
     
    <hibernate-mapping>
        <class name="bean.User" table="t_user">
            <id name="id">
                <generator class="native"/>
            </id>
            <property name="name"/>
            <!-- 使用<set>映射集合,在多对多关系中,Hibernate将生成第三张表 -->
            <set name="groups" table="t_user_group">
                <!-- 使用<key>指定引用至自身的外键表(t_user_group)中的外键 -->
                <key column="userid"/>
                <!-- 使用<many-to-many>映射多对多关系,column指定另一端在表t_user_group中的列 -->
                <many-to-many class="bean.Group" column="groupid"/>
            </set>
        </class>
    </hibernate-mapping>
    1
    2
    3
    4
    5
    6
    7
    8
    <!-- bean/Group.hbm.xml -->
     
    <hibernate-mapping>
        <class name="bean.Group" table="t_group">
            <id name="id"><generator class="native"/></id>
            <property name="name"/>
        </class>
    </hibernate-mapping>
    1、多对多单向关联

    实体模型: 
    bean.User(int id, String name, Set groups
    bean.Group(int id, String name, Set users)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <!-- bean/User.hbm.xml -->
     
    <hibernate-mapping>
        <class name="bean.User" table="t_user">
            <id name="id">
                <generator class="native"/>
            </id>
            <property name="name"/>
            <!-- 使用<set>映射集合,在多对多关系中,Hibernate将生成第三张表 -->
            <set name="groups" table="t_user_group">
                <!-- 使用<key>指定引用至自身的外键表(t_user_group)中的外键 -->
                <key column="userid"/>
                <!-- 使用<many-to-many>映射多对多关系,column指定另一端在表t_user_group中的列 -->
                <many-to-many class="bean.Group" column="groupid"/>
            </set>
        </class>
    </hibernate-mapping>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <!-- bean/Group.hbm.xml -->
     
    <hibernate-mapping>
        <class name="bean.Group" table="t_group">
            <id name="id">
                <generator class="native"/>
            </id>
            <property name="name"/>
            <!-- 使用<set>映射集合,在多对多关系中,Hibernate将生成第三张表 -->
            <set name="users" table="t_user_group">
                <!-- 使用<key>指定引用至自身的外键表(t_user_group)中的外键 -->
                <key column="group"/>
                <!-- 使用<many-to-many>映射多对多关系,column指定另一端在表t_user_group中的列 -->
                <many-to-many class="bean.User" column="userid"/>
            </set>
        </class>
    </hibernate-mapping>

    多对多的双向关联同样可以在不想要维护关系的一端的<set>里设置inverse=”true”;但是必须有一端可以维护,也就是说只可以设置一个。

  • 相关阅读:
    iOS10权限声明国际化
    用"僵尸对象"调试内存管理问题
    windows系统下的两个批处理命令
    解决windows系统下打开应用弹出丢失libmysql.dll的问题
    简单的cocos2dx笔试题
    解决cocos2dx 3.x 导入cocostudio的ui界面出现错位问题
    mac 使用homebrew 安装mysql
    cocos2dx for lua 简单的翻牌动画
    cocos2dx for lua A*寻路算法实现2
    解决升级mac os X EI Capitan后遇到LibclangError: dlopen(libclang.dylib, 6): image not found.的问题
  • 原文地址:https://www.cnblogs.com/rixiang/p/5172868.html
Copyright © 2011-2022 走看看