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>
<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--关联映射(一对多)的更多相关文章
- (转)Hibernate关联映射——一对多(多对一)
http://blog.csdn.net/yerenyuan_pku/article/details/70152173 Hibernate关联映射——一对多(多对一) 我们以客户(Customer)与 ...
- Hibernate关联映射(一对多/多对多)
版权声明:翀版 https://blog.csdn.net/biggerchong/article/details/843401053. Hibernate关联映射上接Hibernate持久化类:h ...
- Hibernate关联映射关系
Hibernate关联映射关系 一.双向一对多关联映射关系:当类与类之间建立了关联,就可以方便的从一个对象导航到另一个或另一组与它关联的对象(一对多双向关联和多对一双向关联是完全一样的) 1.1创建实 ...
- 第六章 Hibernate关联映射
第六章 hibernate关联映射一.本章知识点分为2部分:1.关联关系:单向多对一关联关系,双向一对多关联关系(含一对多关联关系),多对多关联关系2.延迟加载:类级别加载策略,一对多加载策略,多对一 ...
- 【学习笔记】Hibernate关联映射(Y2-1-6)
Hibernate关联映射 关联映射就是将关联关系映射到数据库里,在对象模型中就是一个或多个引用. 1.单向多对一关联 准备数据库 部门表和员工表 其中部门表有两列 部门编号和名称 员工表有三列 员工 ...
- 第三章Hibernate关联映射
第三章Hibernate关联映射 一.关联关系 类与类之间最普通的关系就是关联关系,而且关联是有方向的. 以部门和员工为列,一个部门下有多个员工,而一个员工只能属于一个部门,从员工到部门就是多对一关联 ...
- (转)Hibernate关联映射——对象的三种关系
http://blog.csdn.net/yerenyuan_pku/article/details/70148618 Hibernate关联映射——对象的三种关系 Hibernate框架基于ORM设 ...
- Oracle primary,unique,foreign 区别,Hibernate 关联映射
Oracle primary,unique,foreign 区别 转:http://www.cnblogs.com/henw/archive/2012/08/15/2639510.html NOT N ...
- Hibernate关联映射(单项多对一和一对多、双向一对多)
最近总是接触着新的知识点来扩展自己的知识面:不停的让自己在原地接触天空的感觉真的很美好!!!革命没有成功,程序员的我们怎么能不努力呢...... 一.用员工和部门来剖析关联映射的原理. 1)从这张截图 ...
- Hibernate之关联映射(一对多和多对一映射,多对多映射)
~~~接着之前的Hibernate框架接着学习(上篇面试过后发现真的需要学习以下框架了,不然又被忽悠让去培训.)~~~ 1:Hibernate的关联映射,存在一对多和多对一映射,多对多映射: 1.1: ...
随机推荐
- iOS中的堆(heap)和栈(stack)的理解
操作系统iOS 中应用程序使用的计算机内存不是统一分配空间,运行代码使用的空间在三个不同的内存区域,分成三个段:“text segment “,“stack segment ”,“heap segme ...
- html5游戏引擎-Pharse.js学习笔记(一)
1.前言 前几天随着flappy bird这样的小游戏的火爆,使我这种也曾了解过html5技术的js业余爱好者也开始关注游戏开发.研究过两个个比较成熟的html5游戏引擎,感觉用引擎还是要方便一些.所 ...
- openmeetings 视频会议系统介绍
在功能上,视频会议具有如下特点(这一部分转自:http://www.kissthink.com/archive/5150.html): 1.该方基于P2P技术,服务器压力小.流畅.用户之间可以互相获取 ...
- iOS$299企业账号In House ipa发布流程
1.在Mac系统中进入“钥匙串访问”,选择“钥匙串访问”-“证书助理”-“从证书颁发机构请求证书”. 填写前两项,并保存在本地. 2.登录https://developer.apple.com,进入i ...
- Codeforces Round #302 (Div. 2) D. Destroying Roads 最短路
题目链接: 题目 D. Destroying Roads time limit per test 2 seconds memory limit per test 256 megabytes input ...
- Windows Server 2008下共享资源访问走捷径 (不用用户名 和 密码 访问共享)
1. 启用来宾帐号2. 共享目录添加“Guest”帐号3. “gpedit.msc”,打开对应系统的组策略编辑窗口;在该编辑窗口的左侧显示区域,依次展开“本地计算机策略”/“计算机配置”/“Windo ...
- ${fn:length(worklicenseList)} #表示不在struts堆栈里,没有#表示从struts堆栈里取
${fn:length(worklicenseList)} #表示不在struts堆栈里,没有#表示从struts堆栈里取
- 【redis】04set类型和zset类型
sets类型 sets类型及操作 Set类型是一个集合,他是string类型的无序集合,也就是说咱们的set是没有顺序的, Set是通过hash table实现的,添加.删除和查找的复杂度都是 ...
- Lua 简单的IO交互 和迷宫代码
function room1 () print("in room1") local move = io.read() if move == "south" th ...
- POJ 1363 Rails(栈)
思路:将出车站的顺序存入数组train,由于入车站的顺序是固定的,为1~N,所以用P表示进站的车,初始为1. 接下来举例说明吧: 原来入站顺序: 1 2 3 4 5 读入的出战顺序: 3 4 2 ...