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

实例场景:班级对学生;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. Hadoop2

    http://www.cnblogs.com/miaoxiaoyu/archive/2012/07/29/2614060.html

  2. Qt postEvent

    Qt3中可以直接向线程发送消息 QThread::postEventQ4中已不支持为了模拟向线程发送消息,可以通过QObject::moveToThread后,然后再向这个QObject发送消息 ob ...

  3. 如何用jmeter对websock和protobuf进行压力测试

    1. 一个websocket插件官网地址 https://github.com/maciejzaleski/JMeter-WebSocketSampler 2. 可以用上述插件,也可以自己扩展,以实现 ...

  4. 2437: [Noi2011]兔兔与蛋蛋 - BZOJ

    Description Input 输入的第一行包含两个正整数 n.m.接下来 n行描述初始棋盘.其中第i 行包含 m个字符,每个字符都是大写英文字母"X".大写英文字母" ...

  5. 1654 方程的解 - Wikioi

    题目描述 Description佳佳碰到了一个难题,请你来帮忙解决.对于不定方程a1+a2+… +ak-1 +ak=g(x),其中k≥2且k ∈ N*,x是正整数,g(x) =xx mod 1000( ...

  6. shell uniq sort -u 去重排序

    sort -u 和 uniq都能起到删除重复信息的功能,那么他们的区别究竟在哪呢? $ cat test jason jason jason fffff jason 下面分别执行三个命令 :sort ...

  7. MyEclipse2015破解版_MyEclipse 2015 stable 2.0 稳定版 破解日志

    前言:在MyEclipse 2015 Stable 1.0下载安装破解日志(http://www.cnblogs.com/wql025/p/5161979.html)一文中,笔者主要讲述了该版本的破解 ...

  8. 【BZOJ】【1430】小猴打架

    排列组合 蛮逗的…… 这题题干描述的就一股浓浓的Kruskal的气息……很容易就想到是求一个n个点的完全图的生成树个数,然后由于有序,再乘一个n-1的排列数(n-1条边的全排列)即(n-1)! 但是我 ...

  9. jquery easyui datagrid 获取选中多行

    var rows = $('#dataTable').datagri('getSelections');

  10. iOS开发之静态库的制作

    当你需要和别人分享代码,但又不想让别人看到你内部的实现时就需要制作静态库,通常用于第三方SDK 下面就分享一下制作静态库(.a)的过程: 1.打开Xcode,新建workspace 2.随便给work ...