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

来源:互联网 发布:mac笔记本配置交换机 编辑:程序博客网 时间:2024/05/21 11:27

前言

  在关联映射中,我们对每一种映射,按照对象模型映射原理配置对象存储和加载的顺序来进行介绍。
  这里强调一点,在关系模型中,实体之间的关系是不分方向的,在对象模型中,是分方向的,单向决定了从一端能看到另一端,反之则不行。双向则是两端可以互相看到。

多对一

关系模型

       这里写图片描述

映射原理

     这里写图片描述

  刚才我们提到在关系模型中,对象之间的关系是部分方向的,所以当它们转化成数据库中的表时,不管是多对一,还是我们接下来要介绍的一对多,都是在“多”的一端加上“一”的主键作为外键。

配置

★User.java

package com.bjpowernode.hibernate;public class User {    private int id;    private String name;    //关联对象    private Group group;    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 Group getGroup() {        return group;    }    public void setGroup(Group group) {        this.group = group;    }}

★User.hbm.xml

<hibernate-mapping>    <class name="com.bjpowernode.hibernate.User" table="t_user">        <id name="id">            <generator class="native"/>        </id>        <property name="name"/>        <many-to-one name="group" column="groupid" cascade="save-update"/>    </class></hibernate-mapping>

★Group.java

package com.bjpowernode.hibernate;public class Group {    private int id;    private String name;    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;    }}

★Group.hbm.xml

<hibernate-mapping>    <class name="com.bjpowernode.hibernate.Group" table="t_group">        <id name="id">            <generator class="native"/>        </id>        <property name="name"/>    </class></hibernate-mapping>

小结】:多对一关联映射中,只在“多”的一端的实体中对关联对象进行了引用,并在配置文件中进行了配置,“一”的一端的实体对象未做任何的修改和配置。

对象存储和加载

在学习这块内容中,我们要特别关注以下问题:
1. 对象本身和它关联的对象哪个先实例化,先存储
2. 加载某个对象时,能否也能加载它的关联对象


存储

public void testSave2() {        Session session = null;        try {            session = HibernateUtils.getSession();            session.beginTransaction();            Group group = new Group();            group.setName("动力节点");            //如果使用了级联特性,这句可以省略              session.save(group);            User user1 = new User();            user1.setName("张三");            user1.setGroup(group);            User user2 = new User();            user2.setName("李四");            user2.setGroup(group);            session.save(user1);            session.save(user2);            //可以正确的保存数据            //因为Group和User都是Persistent状态的对象            //所以在hibernate清理缓存时在session中可以找到关联对象            session.getTransaction().commit();        }catch(Exception e) {            e.printStackTrace();            session.getTransaction().rollback();        }finally {            HibernateUtils.closeSession(session);        }    }

小结】:存储的时候,一般先存储关联的对象,再存储自身,目的是让关联的对象也变成Persistent状态。当然我们也可以在配置文件中加入cascade=”save-update”,这样就不用显示的调用session.save(group)来对关联对象进行存储了。


加载

public void testLoad1() {        Session session = null;        try {            session = HibernateUtils.getSession();            session.beginTransaction();            User user = (User)session.load(User.class, 2);//发sql语句            System.out.println("user.name=" + user.getName());            System.out.println("user.group.name=" + user.getGroup().getName());//发sql语句            session.getTransaction().commit();        }catch(Exception e) {            e.printStackTrace();            session.getTransaction().rollback();        }finally {            HibernateUtils.closeSession(session);        }    }

小结】:
1. 我们看到在加载用户对应的组时,通过user.getGroup().getName()就可以加载,但是假如先通过load获得group,这里是不能通过group.getUser()来获得这个组中的用户的,因为在group中并没有进行配置。
2.Hibernate默认支持延迟加载,即<class name="com.bjpowernode.hibernate.User" table="t_user" lazy="true">,此时默认的抓取策略为<many-to-one name="group" column="groupid" cascade="save-update" fetch="select"/>,抓取策略指如何获取关联对象的策略,当使用fetch=”select”时,会先发出第一条sql语句查询当前对象,当使用到关联对象的属性时(查询user对应的组的名称),才会发出第二条sql语句。

总结

  以上是最简单的关联映射,如果能从最简单的关联映射中总结出一些基本规律,那么学习之后的关联映射就会容易许多。在配置关系时,我们自己首先要清楚:要从哪个对象看到哪个对象以及谁来维护它们的关系。

0 0
原创粉丝点击