hibernate 映射 多对一
一对多和上文讲的多对一两种映射关系,其实就是站在相反的角度考虑同样的事情。
一对多和多对一映射原理是一样的,都在多的一端加入一个外键指向一的一端。也就是说,在关系数据库的表中,他们的表及表字段都是一样的。
他们的不同在于维护的关系:
多对一维护的关系——多指向一的关系,如果维护了多指向一的关系,那么加载多的时候会把一加载上来。
一对多维护的关系——一指向多的关系,如果维护了一指向多的关系,那么加载多的时候,会把一加载上来。
现在假如要用一对多映射描述学生和班级的关系。
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 映射 多对一的更多相关文章
- 【SSH系列】Hibernate映射 -- 多对多关联映射
映射原理 在数据库学习阶段,我们知道,如果实体和实体之间的关系是多对多,那么我们就抽出来第三张表,第一张表和第二张表的主键作为第三表的联合主键,结合我们的hibernate,多对多关联,无论 ...
- Hibernate 映射多对多关联关系
映射多对多,需要建立一张中间表 一共三张表,一个是 Category,一个是 Item,还有一个是 Categories_Items Categories_Items 作为中间表,其包含两个列,分别对 ...
- 【SSH进阶之路】Hibernate映射——多对多关联映射(八)
上篇博文[SSH进阶之路]Hibernate映射——一对多关联映射(七),我们介绍了一对多关联映射,它是多对多关联映射的基础. 多对多映射是现实生活中最常见的映射,也是最容易理解的映射.废话少说,直接 ...
- (Hibernate进阶)Hibernate映射——多对多关联映射(八)
多对多映射是现实生活中最常见的映射,也是最容易理解的映射.废话少说,直接开始. 映射原理 不论是单向关联还是双向关联都是通过第三张表,将两个表中的主键放到第三张做一个关联.用第三张表来解决可能会造成数 ...
- (Hibernate进阶)Hibernate映射——多对一单向关联映射(四)
介绍基于基本映射的关联关系映射. 概念 基本映射是对一个实体进行映射,关联映射就是处理多个实体之间的关系,将关联关系映射到数据库中,所谓的关联关系在对象模型中有一个或多个引用. 分类 关联关系分为上述 ...
- Hibernate映射多对多双向关联关系(小案例)
多对多双向关联关系(Project(工程)/Emp(员工)为案例): 步骤如下: 1.创建Project类,并需要定义集合类型的Emp属性 public class Project { //编号 pr ...
- 【SSH进阶之路】Hibernate映射——多对一单向关联映射(四)
[SSH进阶之路]Hibernate基本原理(一) ,小编介绍了Hibernate的基本原理以及它的核心,採用对象化的思维操作关系型数据库. [SSH进阶之路]Hibernate搭建开发环境+简单实例 ...
- 【SSH系列】Hibernate映射-- 多对一单向关联映射
在hibernate中非常重要的就是映射,在前面的博文中,小编简单的介绍了基本映射,基本映射是对一个实体进行映射,关联映射就是处理多个实体之间的关系,将关联关系映射到数据库中,所谓的关联关系在对象模型 ...
- Hibernate -- 映射多对多双向关联关系
1. 示例代码: Student.java package cn.itcast.many2many; import java.util.HashSet; import java.util.Set; @ ...
随机推荐
- poj3468 A Simple Problem with Integers (线段树区间最大值)
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 92127 ...
- halcon的算子列表
Chapter 1 :Classification 1.1 Gaussian-Mixture-Models 1.add_sample_class_gmm 功能:把一个训练样本添加到一个高斯混合模型的训 ...
- 跟我学STL系列(1)——STL入门介绍
一.引言 最近这段时间一直都在自学C++,所以这里总结下自己这段时间的学习过程,通过这种方式来巩固自己学到的内容和以备后面复习所用,另外,希望这系列文章可以帮助到其他自学C++的朋友们. 由于本人之前 ...
- 大熊君说说JS与设计模式之------代理模式Proxy
一,总体概要 1,笔者浅谈 当我们浏览网页时,网页中的图片有时不会立即展示出来,这就是通过虚拟代理来替代了真实的图片,而代理存储了真实图片的路径和尺寸,这就是代理方式的一种. 代理模式是比较有用途的一 ...
- C# 6.0那些事
这两天期中考试没时间去看Connect();直播,挺可惜的,考完后补看了Connect(); 把C#6.0的新东西总结一下. 自动属性初始化 (Initializers for auto-proper ...
- 解决Eclipse Debug source not found问题
解决方法如下:Debug 视图下-->在调试的线程上 右键单击-->选择Edit Source Lookup Path-->选择Add-->选择Java Project选择相应 ...
- Backbone事件管理——Backbone.Events模块API结构
模块Backbone.Events的事件管理是通过Backbone提供的Events API来实现的,该API在1.0版本之前仅仅提供了几个基本的方法,如on.off.trigger.once分别执行 ...
- 在Mac OS上安装Vagrant和Docker的教程
转载于:http://www.itxuexiwang.com/a/shujukujishu/redis/2016/0216/128.html?1455808640 当听到很多人在说Docker是多么多 ...
- maven nexus 3 third party 构件上传
mvn -e deploy:deploy-file -DgroupId=com.oracle -DartifactId=JDBCDriver -Dversion=12.0.1 -Dpackaging= ...
- PHP与Java进行通信
缘起: 最近做了一个电商平台与网银整合的小东西,程序是开源的 Ecmall的,网银的接口也很规范,给出的文档很全,唯一的小问题是,网银使用的签名和验签的lib是只有java和c的,对java还熟悉一些 ...