hibernate--关联映射(一对多)

在对象模型中,一对多的关联关系,使用集合来表示。

实例场景:班级对学生;Classes(班级)和Student(学生)之间是一对多的关系。

对象模型:

多对一、一对多的区别:

多对一关联映射:在多的一端加入一个外键指向一对一端,它维护的关系是多指向一的。

一对多关联映射:在多的一端加入一个外键指向一对一端,它维护的关系是一指向多的。

两者使用的策略是一样的,只是各自所站的角度不同。

Classes实体类:

public class Classes {
    private int id;
    private String name;
}

Students实体类:

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

    //一对多通常使用Set来映射,Set是不可重复内容。
    //注意使用Set这个接口,不要使用HashSet,因为hibernate有延迟加载,
    private Set students;
}

Student映射文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="h.one.bean">
    <class name="Student" table="t_student">
        <id name="id" column="id">
            <generator class="native" />
        </id>
        <property name="name" column="name" />
    </class>
</hibernate-mapping>

Classes映射文件:

<hibernate-mapping package="h.one.bean">
    <class name="Classes" table="t_classess">
        <id name="id" column="id">
            <generator class="native" />
        </id>
        <property name="name" column="name" />
        <!--<set>标签 映射一对多(映射set集合),name="属性集合名称",然后在用<key>标签,在多的一端加入一个外键(column属性指定列名称)指向一的一端,再采用<one-to-many>标签说明一对多,还指定<set>标签中name="students"这个集合中的类型要使用完整的类路径(例如:class="com.wjt276.hibernate.Student") -->
        <set name="students">
            <key column="classesid" />
            <one-to-many class="com.wjt276.hibernate.Student" />
        </set>
    </class>
</hibernate-mapping>

一对多 单向存储实例:

session = HibernateUtil.getSession();
        tx = session.beginTransaction();

        Student student1 = new Student();
        student1.setName("10");
        session.save(student1);// 必需先存储,否则在保存classess时出错.

        Student student2 = new Student();
        student2.setName("祖儿");
        session.save(student2);// 必需先存储,否则在保存classess时出错.

        Set<Student> students = new HashSet<Student>();
        students.add(student1);
        students.add(student2);

        Classes classes = new Classes();
        classes.setName("wjt276");
        classes.setStudents(students);

        session.save(classes);

        // 提交事务
        tx.commit();

一对多,在一的一端维护关系的缺点:

因为是在一的一端维护关系,这样会发出多余的更新语句,这样在批量数据时,效率不高。

还有一个,当在多的一端的那个外键设置为非空时,则在添加多的一端数据时会发生错误,数据存储不成功。

一对多 单向数据加载:

session = HibernateUtil.getSession();
        tx = session.beginTransaction();

        Classes classes = (Classes) session.load(Classes.class, 2);
        System.out.println("classes.name=" + classes.getName());
        Set<Student> students = classes.getStudents();
        for (Iterator<Student> iter = students.iterator(); iter.hasNext();) {
            Student student = iter.next();
            System.out.println(student.getName());
        }
        // 提交事务
        tx.commit();

一对多关联映射 双向(one-to-many)

是加载学生时,能够把班级加载上来。当然加载班级也可以把学生加载上来

1、 在学生对象模型中,要持有班级的引用,并修改学生映射文件就可以了。。

2、 存储没有变化

3、 关系模型也没有变化

学生映射文件修改后的:

<hibernate-mapping>
    <class name="h.one.bean.Student" table="t_student">
        <id name="id" column="id">
            <generator class="native"/>
        </id>
        <property name="name" column="name"/>
        <!--
            使用多对一标签映射 一对多双向,下列的column值必需与多的一端的key字段值一样。
         -->
        <many-to-one name="classes" column="classesid"/>
    </class>
</hibernate-mapping>

session = HibernateUtils.getSession();
            tx = session.beginTransaction();

            Classes classes = new Classes();
            classes.setName("wjt168");
            session.save(classes);

            Student student1 = new Student();
            student1.setName("10");
            student1.setClasses(classes);
            session.save(student1);

            Student student2 = new Student();
            student2.setName("祖儿");
            student2.setClasses(classes);
            session.save(student2);

            //提交事务
            tx.commit();

注意:一对多,从多的一端保存数据比从一对一端保存数据要快,因为从一对一端保存数据时,会多更新多的一端的一个外键(是指定一的一端的。)

如果在一对多的映射关系中采用一的一端来维护关系的话会存在以下两个缺点:①如果多的一端那个外键设置为非空时,则多的一端就存不进数据;②会发出多于的Update语句,这样会影响效率。所以常用对于一对多的映射关系我们在多对一端维护关系,并让多对一端维护关系失效(见下面属性)。

<hibernate-mapping>
    <class name="h.one.bean.Classes" table="t_classes">
        <id name="id" column="id">
            <generator class="native"/>
        </id>
        <property name="name" column="name"/>

        <!--
            <set>标签 映射一对多(映射set集合),name="属性集合名称"
            然后在用<key>标签,在多的一端加入一个外键(column属性指定列名称)指向一的一端
            再采用<one-to-many>标签说明一对多,还指定<set>标签中name="students"这个集合中的类型
            要使用完整的类路径(例如:class="com.wjt276.hibernate.Student")
            inverse="false":一的一端维护关系失效(反转) :false:可以从一的一端维护关系(默认);true:从一的一端维护关系失效,这样如果在一的一端维护关系则不会发出Update语句。
         -->
        <set name="students" inverse="true">
            <key column="classesid"/>
            <one-to-many class="h.one.bean.Student"/>
        </set>
    </class>
</hibernate-mapping>

关于inverse属性:

inverse主要用在一对多和多对多双向关联上,inverse可以被设置到集合标签<set>上,默认inverse为false,所以我们可以从一对一端和多对一端维护关联关系,如果设置inverse为true,则我们只能从多的一端维护关联关系。

注意:inverse属性,只影响数据的存储,也就是持久化

Inverse和cascade区别:

Inverse是关联关系的控制方向

Casecade操作上的连锁反应

一对多双向关联映射总结:

在一对一端的集合上使用<key>,在对方表中加入一个外键指向一对一端

在多对一端采用<many-to-one>

注意:<key>标签指定的外键字段必须和<many-to-one>指定的外键字段一致,否则引用字段的错误

如果在一对一端维护一对多的关系,hibernate会发出多余的update语句,所以我们一般在多对一端来维护关系。

多对多关联映射 单向(many-to-many)

? 一般的设计中,多对多关联映射,需要一个中间表

? Hibernate会自动生成中间表

? Hibernate使用many-to-many标签来表示多对多的关联

? 多对多的关联映射,在实体类中,跟一对多一样,也是用集合来表示的。

实例场景:

用户与他的角色(一个用户拥有多个角色,一个角色还可以属于多个用户)

对象模型:

多对多关联映射 单向数据存储:

@Test
    public void testManyToMany(){
        session = HibernateUtil.getSession();
        tx = session.beginTransaction();

        Role r1 = new Role();
        r1.setName("数据录入人员");
        session.save(r1);

        Role r2 = new Role();
        r2.setName("商务主管");
        session.save(r2);

        Role r3 = new Role();
        r3.setName("大区经理");
        session.save(r3);

        Users u1 = new Users();
        u1.setName("10");
        Set<Role> u1Roles = new HashSet<Role>();
        u1Roles.add(r1);
        u1Roles.add(r2);
        u1.setRoles(u1Roles);

        Users u2 = new Users();
        u2.setName("祖儿");
        Set<Role> u2Roles = new HashSet<Role>();
        u2Roles.add(r2);
        u2Roles.add(r3);
        u2.setRoles(u2Roles);

        Users u3 = new Users();
        u3.setName("成龙");
        Set<Role> u3Roles = new HashSet<Role>();
        u3Roles.add(r1);
        u3Roles.add(r2);
        u3Roles.add(r3);
        u3.setRoles(u3Roles);

        session.save(u1);
        session.save(u2);
        session.save(u3);

        tx.commit();
    }

多对多关联映射 单向数据加载:

多对多关联映射 双向(many-to-many)

<hibernate-mapping>
    <class name="h.one.bean.Role" table="t_role">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name" column="name"/>
        <!— order-by 属性是第三方表哪个字段进行排序-->
        <set name="users" table="t_user_role" order-by="userid">
            <key column="roleid"/>
            <many-to-many class="h.one.bean.Users" column="userid"/>
        </set>
    </class>
</hibernate-mapping>

注:数据的存储与单向一样。但一般维护这个多对多关系,只需要使用一方,而使另一方维护关系失效。

多对多关联映射 双向 数据加载

session = HibernateUtil.getSession();
            tx = session.beginTransaction();

            Role role = (Role)session.load(Role.class, 1);
            System.out.println("role.name=" + role.getName());
            for (Iterator<UserS> iter = role.getUsers().iterator();iter.hasNext();){
                User user = iter.next();
                System.out.println("user.name=" + user.getName());
            }
            //提交事务
            tx.commit();

总结:

? table属性值必须和单向关联中的table属性值一致

? <key>中column属性值要与单向关联中的<many-to-many>标签中的column属性值一致

? 在<many-to-many>中的column属性值要与单向关联中<key>标签的column属性值一致。

hibernate--关联映射(一对多)

时间: 2024-10-06 00:53:42

hibernate--关联映射(一对多)的相关文章

hibernate关联映射(一对多)

这篇博客将会给大家带来hibernate的关联映射的学习.在现实生活中,不仅只是一对一的映射关系,更多的是一对多,多对多等. 一对多单项关联映射 这里我以网盘为例,一个用户可以拥有多个文件,及用户和文件之间是一对多的关系. user实体类: public class Users { private int uid; private String uname; //用户上传的所有文件 // one方 可以获取 many方 private Set<UpFile> files = new HashS

第六章 Hibernate关联映射

第六章 hibernate关联映射一.本章知识点分为2部分:1.关联关系:单向多对一关联关系,双向一对多关联关系(含一对多关联关系),多对多关联关系2.延迟加载:类级别加载策略,一对多加载策略,多对一加载策略二.关联关系1.单向多对一关联关系1.1.概念(什么是单向多对一关联关系,举例说明)  以部门(Dept).Emp(员工)为例: 从员工角度看部门,是多个员工都在一个部门,这就叫单向 如部门编号为20的部门下可以有n个员工(如scott账户下emp表 empno 为7369,7566,778

Hibernate关联映射(单项多对一和一对多、双向一对多)

最近总是接触着新的知识点来扩展自己的知识面:不停的让自己在原地接触天空的感觉真的很美好!!!革命没有成功,程序员的我们怎么能不努力呢...... 一.用员工和部门来剖析关联映射的原理. 1)从这张截图可以看出我会站在员工的角度讲述:(单向关联) 关系:(多个员工对应一个部门)多对一的关系 意味:多个Emp对象只会引用一个Dept对象 方法:在Emp类中定义一个Dept类型属性,来引用所有关联的Dept对象 eg. 第一步建立两个实体类省略 第二步建立大配置 <?xml version='1.0'

hibernate关联映射

本文可作为北京尚学堂马士兵hibernate课程的学习笔记. hibernate的映射,主要分为一对一,一对多,多对一,多对多,同时还要单向与双向的区别. OK,不要纠结于名字,我们开始看例子. 一对一单向 老公是一个实体,老婆也是一个实体. 一个老公只有一个老婆,同时一个老婆也只有一个老公. 上面的关系就叫做一对一. 什么叫单向呢. 看代码: package com.bjsxt.hibernate; @Entity public class Husband { private int id;

Hibernate关联映射 映射文件的配置

一:多对一单向关联 首先我们必须创建两个实体类 例如:Dept类 public class Dept { private Integer deptNo; private String dName; private String loc; private Set<Employee> emps=new HashSet<Employee>(); Employee类 public class Employee { private Integer empno; private String

Hibernate关联映射及高级查询

一.Hibernate中的关联关系 1.1.单向一对多关联关系 按照以下步骤配置hibernate中持久化类的一对多对象关联: (1).持久化类添加关联类的相关属性及getter/setter方法. (2).映射文件中建立该属性和数据库表字段的映射信息. 比如班级对学生是一对多的关系,班级类Grade类和Grade.hbm.xml文件如下: package com.pb.hibernate.po; import java.util.HashSet; import java.util.Set; p

Hibernate关联映射关系

一.双向一对多关联映射关系:当类与类之间建立了关联,就可以方便的从一个对象导航到另一个或另一组与它关联的对象(一对多双向关联和多对一双向关联是完全一样的) 1.1创建实体类(Emp(员工),Dept(部门)) /* * 员工实体类 */public class Emp { private Integer empId; //员工编号 private String empName; //员工姓名 private Dept dept; //所处部门 //get(),set()方法省略 } /* * 部

Hibernate 关联映射

ORM(Object Relational Mapping)对象/关系映射 说到Hibernate的关联映射就必须要提一提ORM了.那么ORM是什么呢,其是一种持久化技术,他在对象模型和关系型数据库之间建立对象关系,通过操作JavaBean对象来完成对数据库的操作! 注意:ORM是概念化的并不是实际存在的,可以理解为其是一种编程思想,而Hibernate框架就是该思想的实现产品! 配置Po对象(和数据表绑定的持久化对象)的关联关系 从上面说到ORM可以在对象模型和数据库之间建立对应关系而在Hib

hibernate关联映射之一对多&amp;多对一

package loaderman.b_one2Many; import java.util.HashSet; import java.util.Set; public class Dept { private int deptId; private String deptName; // [一对多] 部门对应的多个员工 private Set<Employee> emps = new HashSet<Employee>(); public int getDeptId() { re

hibernate关联映射【一对一主键】

从三个部分介绍Hibernate一对一主键关联映射. 1.基本介绍2.代码展示3.总结注意  1.基本介绍 一对一关联有两种情况: 单向一对一主键关联.双向一对一主键关联.一对一主键关联: 是指两个表之间通过主键形成一对一的映射,例如,每个公民只允许拥有一个身份证,公民与身份证就是一对一的关系,定义两张表,一张People表,一张IdCard表,People表的id既是该表的主键也是该表的外键,并且People的id也就是IdCard的id, 2.代码 单向一对一主键关联:people表的id既