一对多和上文讲的多对一两种映射关系,其实就是站在相反的角度考虑同样的事情。

一对多和多对一映射原理是一样的,都在多的一端加入一个外键指向一的一端。也就是说,在关系数据库的表中,他们的表及表字段都是一样的。

他们的不同在于维护的关系:

          多对一维护的关系——多指向一的关系,如果维护了多指向一的关系,那么加载多的时候会把一加载上来。

         一对多维护的关系——一指向多的关系,如果维护了一指向多的关系,那么加载多的时候,会把一加载上来。

现在假如要用一对多映射描述学生和班级的关系。
1、hibernate单向一对多关联映射(Classes----->Student)
实体Classes。一对多关系,加载时需要在一的一端(classes端)加载上来多的一端(Student),所以实体Classes中需包含实体Student的引用。 [java] view plaincopyprint?
01.package com.lzq.hibernate;
02.import java.util.Set;
03.public class Classes {
04. private int id;
05. private String name;
06. private Set student;
07. 此处省略getter和setter方法
08.} 实体Student [java] view plaincopyprint?
01.package com.lzq.hibernate;
02.public class Student {
03. private int id;
04. private String name;
05. 此处省略getter和setter方法
06.}
映射文件Classes.hbm.xml。一对多关系中,需要在多的一端维护关系,所以在Classes端加入“one-to-many”标签维护关系。
[html] view plaincopyprint?
01.<?xml version="1.0"?>
02.<!DOCTYPE hibernate-mapping PUBLIC
03. "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
04. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
05.<hibernate-mapping>
06. <class name="com.lzq.hibernate.Classes" table="t_classes">
07. <id name="id">
08. <generator class="native" />
09. </id>
10. <property name="name" />
11. <!-- 集合映射set-->
12. <set name="student">
13. <!-- 设置classesid外键为非空字段-->
14. <key column="classesid" not-null="true"/>
15. <one-to-many class="com.lzq.hibernate.Student"/>
16. </set>
17. </class>
18.</hibernate-mapping> 映射文件Student.hbm.xml [html] view plaincopyprint?
01.<?xml version="1.0"?>
02.<!DOCTYPE hibernate-mapping PUBLIC
03. "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
04. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
05.<hibernate-mapping>
06. <class name="com.lzq.hibernate.Student" table="t_student">
07. <id name="id">
08. <generator class="native" />
09. </id>
10. <property name="name" />
11. </class>
12.</hibernate-mapping> 尽管我们完成映射,但是这样映射还存在一定的问题,看下面的加载: [java] view plaincopyprint?
01.public void testOne2ManyAdd() throws Exception {
02. Session session=null;
03. Transaction tx=null;
04. try {
05. session=HibernateUtils.getSession();
06. tx=session.beginTransaction();
07. Student student1=new Student();
08. student1.setName("张三");
09. session.save(student1);
10. Classes classes=new Classes();
11. classes.setName("提高班");
12. Set students=new HashSet();
13. students.add(student1);
14. classes.setStudent(students);
15. session.save(classes);
16. tx.commit();
17. } catch (Exception e) {
18. e.printStackTrace();
19. HibernateUtils.closeSession(session);
20. }
21. } 结果会抛PropertyValueException异常。原因很简单:我们在多的一端(Student)没有维护关系,也就是说,Student不知道自己是哪一个班的,所以我们在保存Student的时候关系字段classesid为null。这就限制了外键必须为允许非空,如果外键设置为“不能为空”,则无法进行保存。而我们这里对外键设置,所以才会抛出此异常。
那怎么解决该问题呢?当然,我们可以在Classes.hbm.xml配置中去掉“ not-null='true' ”,这样也可以保存,但是我们可以观察生成的SQL语句,此时进行了一条insert和update语句,显然,它实现插入了student信息,然后在更新的classesid字段。这种方式显然不友善。那么除了这种方式,还能不能用别的方式解决? 这应为此问题,才产生了双向的一对多的关联映射: 2、hibernate双向一对多关联映射(Classes<----->Student) 既然是双向一对多关联映射,那么一定要在多的一端(Student)加入一的一端(Classes)的引用,这样才能在多的一端(Student)进行存储和加载。 [java] view plaincopyprint?
01.package com.lzq.hibernate;
02.public class Student {
03. private int id;
04. private String name;
05.
06. private Classes classes;
07. 此处省略getter/setter方法
08.} 对应配置更改: [html] view plaincopyprint?
01.<?xml version="1.0"?>
02.<!DOCTYPE hibernate-mapping PUBLIC
03. "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
04. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
05.<hibernate-mapping>
06. <class name="com.lzq.hibernate.Student" table="t_student">
07. <id name="id">
08. <generator class="native" />
09. </id>
10. <property name="name" />
11. <!-- 此处需要与classes端的配置的字段保持一致-->
12. <many-to-one name="classes" column="classesid" />
13. </class>
14.</hibernate-mapping> 此外,既然双向一对多关联映射的产生是为了弥补单向一对多关联映射的缺陷,那么避免程序员编写程序仍然在一的一端(Classes)加载,我们可以采用反转技术,设置从Classes端加载失效: [html] view plaincopyprint?
01.<?xml version="1.0"?>
02.<!DOCTYPE hibernate-mapping PUBLIC
03. "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
04. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
05.<hibernate-mapping>
06. <class name="com.lzq.hibernate.Classes" table="t_classes">
07. <id name="id">
08. <generator class="native" />
09. </id>
10. <property name="name" />
11. <!--反转:设置从Classes端加入数据失效-->
12. <set name="student" inverse="true">
13. <key column="classesid" />
14. <one-to-many class="com.lzq.hibernate.Student"/>
15. </set>
16. </class>
17.</hibernate-mapping> 为什么多对一关联映射不存在单向一对多中的问题呢?如果你明白了上面所讲的,这个问题将很好回答。在多对一关联映射里面,由于关系是在多的一端进行维护的,加载的时候从多的一端进行加载,当然没有问题。 总结一下:在多对一关联映射中,如果用到,经常采用双向的方式来完成映射,弥补单向加载时的问题。

hibernate 映射 多对一的更多相关文章

  1. 【SSH系列】Hibernate映射 -- 多对多关联映射

         映射原理 在数据库学习阶段,我们知道,如果实体和实体之间的关系是多对多,那么我们就抽出来第三张表,第一张表和第二张表的主键作为第三表的联合主键,结合我们的hibernate,多对多关联,无论 ...

  2. Hibernate 映射多对多关联关系

    映射多对多,需要建立一张中间表 一共三张表,一个是 Category,一个是 Item,还有一个是 Categories_Items Categories_Items 作为中间表,其包含两个列,分别对 ...

  3. 【SSH进阶之路】Hibernate映射——多对多关联映射(八)

    上篇博文[SSH进阶之路]Hibernate映射——一对多关联映射(七),我们介绍了一对多关联映射,它是多对多关联映射的基础. 多对多映射是现实生活中最常见的映射,也是最容易理解的映射.废话少说,直接 ...

  4. (Hibernate进阶)Hibernate映射——多对多关联映射(八)

    多对多映射是现实生活中最常见的映射,也是最容易理解的映射.废话少说,直接开始. 映射原理 不论是单向关联还是双向关联都是通过第三张表,将两个表中的主键放到第三张做一个关联.用第三张表来解决可能会造成数 ...

  5. (Hibernate进阶)Hibernate映射——多对一单向关联映射(四)

    介绍基于基本映射的关联关系映射. 概念 基本映射是对一个实体进行映射,关联映射就是处理多个实体之间的关系,将关联关系映射到数据库中,所谓的关联关系在对象模型中有一个或多个引用. 分类 关联关系分为上述 ...

  6. Hibernate映射多对多双向关联关系(小案例)

    多对多双向关联关系(Project(工程)/Emp(员工)为案例): 步骤如下: 1.创建Project类,并需要定义集合类型的Emp属性 public class Project { //编号 pr ...

  7. 【SSH进阶之路】Hibernate映射——多对一单向关联映射(四)

    [SSH进阶之路]Hibernate基本原理(一) ,小编介绍了Hibernate的基本原理以及它的核心,採用对象化的思维操作关系型数据库. [SSH进阶之路]Hibernate搭建开发环境+简单实例 ...

  8. 【SSH系列】Hibernate映射-- 多对一单向关联映射

    在hibernate中非常重要的就是映射,在前面的博文中,小编简单的介绍了基本映射,基本映射是对一个实体进行映射,关联映射就是处理多个实体之间的关系,将关联关系映射到数据库中,所谓的关联关系在对象模型 ...

  9. Hibernate -- 映射多对多双向关联关系

    1. 示例代码: Student.java package cn.itcast.many2many; import java.util.HashSet; import java.util.Set; @ ...

随机推荐

  1. poj3468 A Simple Problem with Integers (线段树区间最大值)

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 92127   ...

  2. ES6 fetch函数与后台交互

    最近在学习react-native,遇到调用后端接口的问题.看了看官方文档,推荐使用es6的fetch来与后端进行交互,在网上找了一些资料.在这里整理,方便以后查询. 1.RN官方文档中,可使用XML ...

  3. Google Chrome: Make the Bookmarks Bar Display as Icons Only

    By reducing your bookmarks to show only the icons, you can access more of them from the Bookmarks ba ...

  4. JS 将字符串转换成日期类型

    将字符串形式的日期转换成日期对象 var strTime="2011-04-16"; //字符串日期格式           var date= new Date(Date.par ...

  5. 用word-break: break-all解决不正确换行问题

    这个在新闻频道存在已久的问题,今天终于把它给解决了! 问题是这样的,当一段文字中有比较长的链接地址,会造成链接地址之前的文字不能正确换行,效果如下: 对应的html代码如下: <p> 如图 ...

  6. 设计模式之美:Facade(外观)

    索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):用抽象类定义 Facade 而使子类对应于不同的子系统. 意图 为子系统中的一组接口提供一个一致的界面,Facade 模式定义了 ...

  7. 剑指offer 面试题6:重建二叉树

    重建二叉树 题目 输入某二叉树的前序遍历和中序遍历,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含有重复的数字. 例如,前序遍历序列:{1,2,3,7,3,5,6,8},中序遍历序列:{ ...

  8. 云端持续集成——AppVeyor拥抱GitHub

    想着你正在做一个网站 终于大功告成了,提交了代码后,你按下了开发环境的Build菜单,一杯咖啡后,Build Succeed,然后连接服务器,开始部署 当你乐滋滋的享受着你的开发成果时,突然发现了一个 ...

  9. AngularJS快速入门指南05:控制器

    AngularJS控制器用来控制AngularJS applications的数据. AngularJS控制器就是普通的JavaScript对象. AngularJS控制器 AngularJS app ...

  10. Nodejs学习笔记(九)--- 与Redis的交互(mranney/node_redis)入门

    目录 简介和安装 redis简介 redis安装 redis运行 node_redis安装 连接到redis服务器redis.createClient() 认证 client.auth(passwor ...