版权声明:本文为博主原创文章,未经博主允许不得转载。如需转载请声明:【转自 http://blog.csdn.net/xiaoxian8023 】

在上一篇博客《一口一口吃掉Hibernate(四)——多对一单向关联映射》中,介绍了多对一的关联映射,今天就反过来说一下一对多的单向关联映射。

可能有人会对这2篇博客的题目有点混淆不清,跟日常说的关系有点不同。我们日常说的比如父子关系,夫妻关系都是说的双向关系,而现在讨论的则是单向关系,所以也就有了多对一和一对多的说法。

二者的关系其实很简单,只是角度不同而已。比如说学生和班级的关系。如果从学生角度来看,是多对一的关系。而从班级角度来看,则是一对多的关系。说法很简单,但是在对象和关系的建立却是不一样的。

先看一下一对多的类图(貌似好多人的聚合关系都画错了):

hibernate对于一对多的关系的处理,是通过操作Class端,间接操作或者自动操作Student端。比如添加,我直接添加Class端的数据,多个Student就会被添加自动添加进去。也可以通过这个Class获取到所有对应的学生信息。跟着我来配置一下吧:

首先定义实体类【Class】【Student】

  1. package com.bjpowernode.hibernate;
  2. import java.util.Set;
  3. /**
  4. * 班级类
  5. * @author Longxuan
  6. *
  7. */
  8. public class Class {
  9. private int id;
  10. private String name;
  11. private Set<Student> students;
  12. public Set<Student> getStudents() {
  13. return students;
  14. }
  15. public void setStudents(Set<Student> students) {
  16. this.students = students;
  17. }
  18. public int getId() {
  19. return id;
  20. }
  21. public void setId(int id) {
  22. this.id = id;
  23. }
  24. public String getName() {
  25. return name;
  26. }
  27. public void setName(String name) {
  28. this.name = name;
  29. }
  30. }
  31. package com.bjpowernode.hibernate;
  32. /**
  33. * 学生类
  34. * @author Longxuan
  35. *
  36. */
  37. public class Student {
  38. private int id;
  39. private String name;
  40. public int getId() {
  41. return id;
  42. }
  43. public void setId(int id) {
  44. this.id = id;
  45. }
  46. public String getName() {
  47. return name;
  48. }
  49. public void setName(String name) {
  50. this.name = name;
  51. }
  52. }

hibernate.cfg.xml配置文件和hibernate.properties配置文件跟上篇博文中的一致,只是数据库名不同而已。自行修改或者不修改都可。

Hibernate提供了one-to-many来简化一对多的映射关系。不用我们自己再去实现,只需要在映射文件中进行配置即可:

  1. <?xml version="1.0"?>
  2. <!DOCTYPE hibernate-mapping PUBLIC
  3. "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  4. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
  5. <hibernate-mapping package="com.bjpowernode.hibernate">
  6. <class name="Student" table="t_student">
  7. <id name="id">
  8. <generator class="native"/>
  9. </id>
  10. <property name="name"/>
  11. </class>
  12. <class name="Class" table="t_class">
  13. <id name="id">
  14. <generator class="native"/>
  15. </id>
  16. <property name="name"/>
  17. <!-- 设置Set,用于关联多个学生 -->
  18. <set name="students">
  19. <!-- 在t_student表中创建外键classid,与本表的id对应 -->
  20. <key column="classid"></key>
  21. <one-to-many class="Student"></one-to-many>
  22. </set>
  23. </class>
  24. </hibernate-mapping>

配置了one-to-many会自动在t_student表中创建外键classid,与t_class的id映射。

测试类【One2ManyTest】:

  1. package com.bjpowernode.hibernate;
  2. import java.util.HashSet;
  3. import java.util.Iterator;
  4. import java.util.Set;
  5. import junit.framework.TestCase;
  6. import org.hibernate.Session;
  7. import org.hibernate.Transaction;
  8. public class One2ManyTest extends TestCase {
  9. public void testSave2() {
  10. Session session = null;
  11. try {
  12. session = HibernateUtils.getSession();
  13. session.beginTransaction();
  14. Student student1 = new Student();
  15. student1.setName("张三");
  16. //必须先将student1转化为Persistent状态,否则会抛TransientObjectException
  17. session.save(student1);
  18. Student student2 = new Student();
  19. student2.setName("李四");
  20. //必须先将student1转化为Persistent状态,否则会抛TransientObjectException
  21. session.save(student2);
  22. Class classes = new Class();
  23. classes.setName("提高班");
  24. Set<Student> students = new HashSet<Student> ();
  25. students.add(student1);
  26. students.add(student2);
  27. classes.setStudents(students);
  28. //可以成功保存数据。
  29. //先添加数据,将关系字段设置为null,再用update语句来更新关系字段
  30. //但是会发出多余的update语句来维持关系。
  31. session.save(classes);
  32. session.getTransaction().commit();
  33. }catch(Exception e) {
  34. e.printStackTrace();
  35. session.getTransaction().rollback();
  36. }finally {
  37. HibernateUtils.closeSession(session);
  38. }
  39. }

结果图:

执行测试前: ,执行测试后:

虽然最后的结果跟多对一一样,但是根据sql语句,就可以看出,一对多是先添加student,classid为null,等添加了class以后,再执行update语句,把classid更新上去。这样同时可能会暴露一个问题:如果student的classid设置了not-null="true",则会抛PropertyValueException异常。所以不太推荐使用一对多。

通过上面的例子,我们可以看出,其实一对多关联映射和多对一关联映射映射原理是一致的,都是在多的一端加入一个外键,指向一的一端。

它们的区别在于维护的关系不同:

  • 多对一维护的关系是:多指向一的关系,有了此关系,在加载多的时候可以将一加载上来
  • 一对多维护的关系是:一指向多的关系,有了此关系,在加载一的时候可以将多加载上来

在一的一端维护关系存在缺陷:

  • 因为多的一端Student不知道Class的存在(也就是Student没有维护与Class的关系)所以在保存Student的时候关系字段classid是为null的,如果将该关系字段设置为非空,则将无法保存数据
  • 另外因为Student不维护关系,而Class维护关系,Class就会发出多余的update语句,保证Class和Student有关系,这样加载Class的时候才可以把该Class对应的学生加载上来

一口一口吃掉Hibernate(五)——一对多单向关联映射的更多相关文章

  1. Hibernate从入门到精通(八)一对多单向关联映射

    上次的博文Hibernate从入门到精通(七)多对一单向关联映射我们主要讲解了一下多对一单向关联映射,这次我们继续讲解一下一对多单向映射. 一对多单向关联映射 在讲解一对多单向关联之前,按照我们的惯例 ...

  2. Hibernate(八)一对多单向关联映射

    上次的博文Hibernate从入门到精通(七)多对一单向关联映射我们主要讲解了一下多对一单向关联映射, 这次我们继续讲解一下一对多单向映射. 一对多单向关联映射 在讲解一对多单向关联之前,按 照我们的 ...

  3. hibernate之关于一对多单向关联映射

    [hibernate]之关于一对多单向关联映射 基于外键的一对多关联映射! 一对多,Group(组)对于Person(人),一个组能够有多个人!ok? Hibernate主要有两种配置方法.一种是An ...

  4. Hibernate 单项一对多的关联映射

    在上一篇中我们简单介绍了多对一的关联映射,本文介绍hibernate中一对多的关联映射. 1.设计表结构 虽然关联关系由多对一变为一对多,但是我们表结构不会发生改变,只是指向变了. 2.创建stude ...

  5. Hibernate从入门到精通(五)一对一单向关联映射

    上次的博文中Hibernate从入门到精通(四)基本映射我们已经讲解了一下基本映射和相关概念,接下来我们会讲稍微复杂点的映射——关系映射. 关系映射分类 关系映射即在基本映射的基础上处理多个相关对象和 ...

  6. Hibernate(五)一对一单向关联映射

    上次的博文中 Hibernate从入门到精通(四)基本映射我们已经讲解了一下基本映射和相关概念,接下来 我们会讲稍微复杂点的映射——关系映射. 关系映射分类 关系映射即在基本映射的基础上处理 多个相关 ...

  7. [置顶] Hibernate从入门到精通(五)一对一单向关联映射

    上次的博文中Hibernate从入门到精通(四)基本映射我们已经讲解了一下基本映射和相关概念,接下来我们会讲稍微复杂点的映射——关系映射. 关系映射分类 关系映射即在基本映射的基础上处理多个相关对象和 ...

  8. Hibernate 双向一对多的关联映射

    双向的一对多的关联关系是单项的一对多和单项的多对一的情况下产生的. 1.设计表结构 虽然关联关系变为双向的一对多,但是我们表结构不会发生改变,只是指向变了. 2.创建student对象 3.创建Gra ...

  9. Hibernate从入门到精通(九)一对多双向关联映射

    上次的博文Hibernate从入门到精通(八)一对多单向关联映射中,我们讲解了一下一对多单向映射的相关内容,这次我们讲解一下一对多双向映射的相关内容. 一对多双向关联映射 一对多双向关联映射,即在一的 ...

随机推荐

  1. Spring Security入门(3-6)Spring Security 的鉴权 - 自定义权限前缀

  2. css(1-1)样式表

    CSS Id 和 Class id 和 class 选择器 如果你要在HTML元素中设置CSS样式,你需要在元素中设置"id" 和 "class"选择器. id ...

  3. GIT入门笔记(20)- git 开发提交代码过程梳理

    git开发提交流程新项目开发,可以直接往master上提交老项目维护,可以在分支上修改提交,多次add和commit之后,也可以用pull合并主干和本地master,解决冲突后再push 1.检出代码 ...

  4. C++中explicit关键字

    explicit: 防止隐式转换使用. 隐式转换:不同类型的变量可以互相转换,如将一个整形数值赋值给一个类,ClassXX  lei = 4: C++中, 一个参数的构造函数(或者除了第一个参数外其余 ...

  5. 运维-替换kibana徽标

    作为一名纯运维人员,想更改kibana的徽标. 并不能像开发一样去看源码并修改源码. 所以我们可以替换徽标. 先来一个效果图.我的版本是5.5.1. 具体的修改过程: 在kibana安装路径下面. o ...

  6. O(logN)中logN的底数

    转载:http://blog.csdn.net/jdbc/article/details/42173751 问题: 无论是计算机算法概论.还是数据结构书中, 关于算法的时间复杂度很多都用包含O(log ...

  7. Kafka Cached zkVersion [62] not equal to that in zookeeper, skip updating ISR (kafka.cluster.Partition) 问题分析

    我司业务Kafka集群是3节点(broker分别为10,20,30),每个Topic 3 Partition,3 Repilication的配置,早上起床突然发现所有Topic的Broker节点都变为 ...

  8. python基础——继承实现的原理

    python基础--继承实现的原理 1 继承顺序 class A(object): def test(self): print('from A') class B(A): def test(self) ...

  9. 深入浅出Lua虚拟机

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 作者:郑小辉 | 腾讯 游戏客户端开发高级工程师 写在前面:本文所有的文字都是我手工一个一个敲的,以及本文后面分享的Demo代码都是我一行一 ...

  10. Lua中table的实现-《Lua设计与实现》

    本文来自<Lua设计与实现>的阅读笔记,推荐Lua学习者可以购买一本,深入浅出讲解lua的设计和实现原理,很赞,哈哈   Lua中对于表的设计,是基于数组和散列表,和其他语言不同,对于数组 ...