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; @ ...
随机推荐
- link,unlink,remove, rename函数
link函数:创建一个指向现有文件的链接的方法是使用 个人理解为cp命令 #include <unistd.h> int link( const char *existingpath, c ...
- 让谷歌浏览器 chrome 支持小于12px的字体
webkit的私有属性:{-webkit-text-size-adjust:none;} 但是,在最新版的谷歌里.已经不在支持这个属性啦. 用css3的transform:scale()缩放大小,但是 ...
- processing学习笔记
这是从http://funprogramming.org/视频学习过程中做的笔记,没法看视频的话,请FQ 点point(x,y); 线line(x,y,x2,y2); 背景background(x), ...
- Poj-2250-Compromise
题意是找两篇文章中的最长子单词序列 能得出个数,但不知如何输出,找不到路径 看了别人的dfs,有所领悟: 若输入s1:ab,bd,fk,ce,ak,bt,cv s2: ab,fk,ce,tt,ak,b ...
- css伪类运用
<!doctype html><html><head><meta charset="utf-8"><title>CSS输 ...
- poj 1936 All in All
All in All Time Limit: 1000 MS Memory Limit: 30000 KB 64-bit integer IO format: %I64d , %I64u Java ...
- 利用Formdata实现form提交文件上传不跳转页面
作者:幻月九十链接:https://www.zhihu.com/question/19631256/answer/119911045来源:知乎著作权归作者所有,转载请联系作者获得授权. $('form ...
- ASP.NET Web API 2 中的特性路由
ASP.NET MVC 5.1 开始已经支持基于特性的路由(http://attributerouting.net),ASP.NET WEB API 2 同时也支持了这一特性. 启用特性路 由只需要在 ...
- Google 镜像站搜集[转]
Google 镜像站搜集 原文链接:http://www.itechzero.com/google-mirror-sites-collect.html 如果您是以下镜像的作者,并且不希望您的镜像出现在 ...
- 2014-3-5 星期三 [New Change && New Start]
昨日进度: [计算方法]:起晚啦,迟到一点,有点困,可能因为睡得太晚吧! [无课]:制作IEEE标准在JAVA中的应用. [组成]:-- [多媒体]:-- [人工智能]:-- [寝室]:学习API. ...