【Hibernate系列】(六):关联映射之一对多

前言

  在阅读本篇博客之前,请先对多对一关联映射有所了解,可参考【Hibernate系列】(五):关联映射之多对一 。在上篇博客中,我们已经强调过,多对一和一对多的关联映射原理都是在多的一端加入外键。它们在对象模型中的区别就是从谁能看到谁的问题。如:在上篇文章的例子中,通过user可以加载出group来,但是不能通过group来加载user。这篇文章,我们着重强调单纯一对多关系的配置,以及一对多和多对一同时存在时的配置。

一对多

关系模型和映射原理

这里只是方便大家和后面的代码对应。模型和原理同多对一。

   这里写图片描述

  这里写图片描述

配置

★Classes.java

package com.bjpowernode.hibernate;

import java.util.Set;

public class Classes {

    private int id;

    private String name;
    //关联对象集合,没有使用泛型
    private Set students;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set getStudents() {
        return students;
    }

    public void setStudents(Set students) {
        this.students = students;
    }

}

★Classes.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.bjpowernode.hibernate.Classes" table="t_classes">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name"/>
        <set name="students">
            <!--指定外键字段名称-->         
            <key column="classesid"/>
            <!--通过class属性指定关联集合中存储的实体类型-->
            <one-to-many class="com.bjpowernode.hibernate.Student"/>
        </set>
    </class>
</hibernate-mapping>

Students.java和Student.hbm.xml中未进行任何配置,这里省略它们的代码。

对象的存储和加载

  因为只在一端进行了配置,所以我们可以猜到能够通过Classes加载Student,反之则不行。而且这个关联关系也是由Classes来维护的,所以存储的时候,应该先存储Student,再存储Classes。即:关系由谁维护谁就后存储,另外的对象先存储。

public void testSave2() {
        Session session = null;
        try {
            session = HibernateUtils.getSession();
            session.beginTransaction();
            Student student1 = new Student();
            student1.setName("张三");
            session.save(student1);

            Student student2 = new Student();
            student2.setName("李四");
            session.save(student2);

            Classes classes = new Classes();
            classes.setName("动力节点");

            Set students = new HashSet();
            students.add(student1);
            students.add(student2);
            classes.setStudents(students);

            //可以成功保存数据
            //但是会发出多余的update语句来维持关系
            session.save(classes);
            session.getTransaction().commit();
        }catch(Exception e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        }finally {
            HibernateUtils.closeSession(session);
        }
    }

因为关系由class维护,所以先存储student,但是存储student的时候,还不知道classesid是什么,所以代码运行时会打印出以下结果:在save的时候插入数据,在commit的时候更新(外键)。

Hibernate: insert into t_student (name) values (?)
Hibernate: insert into t_student (name) values (?)
Hibernate: insert into t_classes (name) values (?)
Hibernate: update t_student set classesid=? where id=?
Hibernate: update t_student set classesid=? where id=?

发的语句越多说明和数据库交互越多,影响性能。
加载此处省略,可以通过classes加载student。

一对多和多对一结合

单纯的多对一,我们可以通过“多”加载“一”,不能通过“一”加载“多”。
单纯的一对多,我们可以通过“一”加载“多”,不能通过“多”加载“一”,同时还存在影响性能的弊端。
所以,我们可能会单独使用多对一,但是很少会单独的使用一对多。
那么,如何能满足我们的需求,又能避免以上缺点呢?


配置

我们采取的方式一对多和多对一两个关系都配置上,只是关系由多的一方维护,也就是最关键的地方即在一的一端将inverse属性设置为true。
一的一端只修改了配置文件。

<hibernate-mapping>
    <class name="com.bjpowernode.hibernate.Classes" table="t_classes">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name"/>
        <!--inverse设置为true,关系由对端维护-->
        <set name="students" inverse="true">            
            <key column="classesid"/>
            <one-to-many class="com.bjpowernode.hibernate.Student"/>
        </set>
    </class>
</hibernate-mapping>

多的一端的配置参考上一篇文章即可,这里省略.
存储就可以按多对一的时候的存储步骤进行存储了。此时两个对象也可以相互加载了。具体代码参考上一篇博客。

总结

  通过多对一和一对多关联关系的学习,我们可以归纳出,配置<many-to-one><one-to-many>标签决定的是能否加载关联对象;但是关系由谁维护,决定如何存储对象。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值