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

实例场景:班级对学生;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--关联映射(一对多)的更多相关文章

  1. (转)Hibernate关联映射——一对多(多对一)

    http://blog.csdn.net/yerenyuan_pku/article/details/70152173 Hibernate关联映射——一对多(多对一) 我们以客户(Customer)与 ...

  2. Hibernate关联映射(一对多/多对多)

    版权声明:翀版 https://blog.csdn.net/biggerchong/article/details/843401053.  Hibernate关联映射上接Hibernate持久化类:h ...

  3. Hibernate关联映射关系

    Hibernate关联映射关系 一.双向一对多关联映射关系:当类与类之间建立了关联,就可以方便的从一个对象导航到另一个或另一组与它关联的对象(一对多双向关联和多对一双向关联是完全一样的) 1.1创建实 ...

  4. 第六章 Hibernate关联映射

    第六章 hibernate关联映射一.本章知识点分为2部分:1.关联关系:单向多对一关联关系,双向一对多关联关系(含一对多关联关系),多对多关联关系2.延迟加载:类级别加载策略,一对多加载策略,多对一 ...

  5. 【学习笔记】Hibernate关联映射(Y2-1-6)

    Hibernate关联映射 关联映射就是将关联关系映射到数据库里,在对象模型中就是一个或多个引用. 1.单向多对一关联 准备数据库 部门表和员工表 其中部门表有两列 部门编号和名称 员工表有三列 员工 ...

  6. 第三章Hibernate关联映射

    第三章Hibernate关联映射 一.关联关系 类与类之间最普通的关系就是关联关系,而且关联是有方向的. 以部门和员工为列,一个部门下有多个员工,而一个员工只能属于一个部门,从员工到部门就是多对一关联 ...

  7. (转)Hibernate关联映射——对象的三种关系

    http://blog.csdn.net/yerenyuan_pku/article/details/70148618 Hibernate关联映射——对象的三种关系 Hibernate框架基于ORM设 ...

  8. Oracle primary,unique,foreign 区别,Hibernate 关联映射

    Oracle primary,unique,foreign 区别 转:http://www.cnblogs.com/henw/archive/2012/08/15/2639510.html NOT N ...

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

    最近总是接触着新的知识点来扩展自己的知识面:不停的让自己在原地接触天空的感觉真的很美好!!!革命没有成功,程序员的我们怎么能不努力呢...... 一.用员工和部门来剖析关联映射的原理. 1)从这张截图 ...

  10. Hibernate之关联映射(一对多和多对一映射,多对多映射)

    ~~~接着之前的Hibernate框架接着学习(上篇面试过后发现真的需要学习以下框架了,不然又被忽悠让去培训.)~~~ 1:Hibernate的关联映射,存在一对多和多对一映射,多对多映射: 1.1: ...

随机推荐

  1. WPF-控件-编辑圆角TextBox

    使用模板 代码如下: <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xm ...

  2. 【CocoaPods】配置CocoaPods前 - 本地安装好Ruby环境

    xcode (反正就是代码编辑器) Xcode就不用说了把. homebrew (反正就是软件管理器) homebrew是一个包管理器,用于在mac上安装一些os x上没有的UNiX工具(比如wget ...

  3. Very large tabs in eclipse panes on Ubuntu

    http://stackoverflow.com/questions/11805784/very-large-tabs-in-eclipse-panes-on-ubuntu ou can edit E ...

  4. foxmail创建163公司企业邮箱的时候会出现ERR Unable to log on

    foxmail创建163公司企业邮箱的时候会出现ERR Unable to log on 解决办法:把pop.qiye.163.com更改为pop.ym.163.com,瞬间创建成功....也许是网易 ...

  5. 3044 矩形面积求并 - Wikioi

    题目描述 Description 输入n个矩形,求他们总共占地面积(也就是求一下面积的并) 输入描述 Input Description 可能有多组数据,读到n=0为止(不超过15组) 每组数据第一行 ...

  6. java 把URL中的中文转换成utf-8编码

    private static final String QUERY = "餐饮"; String sr = URLEncoder.encode(QUERY); System.out ...

  7. 剑指offer--面试题4

    题目:替换字符串中的空格为“%20”. 说明:在浏览器的地址栏中输入某个网址,在解析过程中会看到类似“%20”的字样,这应该就是网络编程涉及的内容... 该题总体来说比较简单(连我都能想到!),个人认 ...

  8. jsp中文件下载的实现

    jsp中实现文件下载的最简单的方式是在网页上做超级链接,如:<a href="music/abc.mp3">点击下载</a>.但是这样服务器上的目录资源会直 ...

  9. HDU 1087 Super Jumping! Jumping! Jumping!(最长上升子序列,dp)

    以下引用自:http://www.cnblogs.com/Lyush/archive/2011/08/31/2161314.html沐阳 该题可以算是一道经典的DP题了,题中数据是这样的.以 3 1 ...

  10. POJ 1928

    #include <iostream> #include <algorithm> #define MAXN 3000 using namespace std; struct n ...