一对多关系映射大家都明白,关系双方都一个含有对方多个引用,但自身一对多很多同学都不明白什么意思,那么首先我就说明一下什么是自身一对多,其实也很好理解,自身一对多就是自身含有本身的多个引用,例如新闻类别,新闻包含体育新闻和政治新闻,体育新闻内有含有足球新闻和篮球新闻,其实他们都属于新闻,只是名字不同而已,下面我们就以新闻类别为例来具体说明一下:

首先我们来看一下新闻类别的类图:

类图:category

从上面的图我们可以看出:每一个新闻类别都有一个父类别和一个孩子类别的set集合,这个父类别和孩子类别里面都是自身的引用,这样就行了自身一对多的对象关系

下面看一下具体的新闻实体类:Category.Java

  1. public class Category
  2. {
  3. private Long id;
  4. private String name;
  5. private Category parentCategory;
  6. private Set<Category> childCategories;
  7. public Category(String name, Category parentCategory,
  8. Set<Category> childCategories)
  9. {
  10. this.name = name;
  11. this.parentCategory = parentCategory;
  12. this.childCategories = childCategories;
  13. }
  14. public Category()
  15. {
  16. }
  17. *******set、get方法省略
  18. }

看完具体的实体类之后我们下面看一下其具体的配置,其实他的配置中没什么特别的地方,仅仅只是他的配置中包含了一对多和多对一的共同标签存在而已:他即含有多的一方的<set>标签。也含有一的一方的<many-to-one>标签:

Category.hbm.xml配置文件

  1. <?xml version="1.0"?>
  2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  3. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
  4. <hibernate-mapping>
  5. <class name="com.shengsiyuan.hibernate.Category" table="categories">
  6. <id name="id" column="id" type="long">
  7. <generator class="increment"></generator>
  8. </id>
  9. <property name="name" type="string" >
  10. <column name="name" length="50" ></column>
  11. </property>
  12. <set name="childCategories" cascade="all" inverse="true">
  13. <key column="category_id"></key>
  14. <one-to-many class="com.shengsiyuan.hibernate.Category"/>
  15. </set>
  16. <many-to-one name="parentCategory" column="category_id" class="com.shengsiyuan.hibernate.Category">
  17. </many-to-one>
  18. </class>
  19. </hibernate-mapping>

下面我们来看一下在自身一对多的关系下进行增删改查的示例:

  1. import java.util.HashSet;
  2. import org.hibernate.Session;
  3. import org.hibernate.SessionFactory;
  4. import org.hibernate.Transaction;
  5. import org.hibernate.cfg.Configuration;
  6. public class HibernateTest2
  7. {
  8. private static SessionFactory sessionFactory;
  9. static
  10. {
  11. try
  12. {
  13. sessionFactory = new Configuration().configure()
  14. .buildSessionFactory();
  15. }
  16. catch (Exception ex)
  17. {
  18. ex.printStackTrace();
  19. }
  20. }
  21. public static void main(String[] args)
  22. {
  23. Session session = sessionFactory.openSession();
  24. Transaction tx = null;
  25. try
  26. {
  27. tx = session.beginTransaction();
  28. Category category1 = new Category("level1", null, new HashSet<Category>());
  29. Category category2 = new Category("level2", null, new HashSet<Category>());
  30. Category category3 = new Category("level2", null, new HashSet<Category>());
  31. Category category4 = new Category("level3", null, new HashSet<Category>());
  32. Category category5 = new Category("level3", null, new HashSet<Category>());
  33. Category category6 = new Category("level3", null, new HashSet<Category>());
  34. Category category7 = new Category("level3", null, new HashSet<Category>());
  35. category2.setParentCategory(category1);
  36. category3.setParentCategory(category1);
  37. category1.getChildCategories().add(category2);
  38. category1.getChildCategories().add(category3);
  39. category4.setParentCategory(category2);
  40. category5.setParentCategory(category2);
  41. category2.getChildCategories().add(category4);
  42. category2.getChildCategories().add(category5);
  43. category6.setParentCategory(category3);
  44. category7.setParentCategory(category3);
  45. category3.getChildCategories().add(category6);
  46. category3.getChildCategories().add(category7);
  47. Category category = (Category)session.get(Category.class, new Long(1));
  48. System.out.println(category.getChildCategories().iterator().next().getName());
  49. session.delete(category);
  50. tx.commit();
  51. }
  52. catch(Exception ex)
  53. {
  54. if(null != tx)
  55. {
  56. tx.rollback();
  57. }
  58. }
  59. finally
  60. {
  61. session.close();
  62. }
  63. }
  64. }

在很多实际开发过程中,多对多的映射关系也是比较常见的,最为明显的例子就是我们常用的学生选课示例,一个学生可以选多门课,一门课也可以由多个学生去选,这样就形成了多对多的映射关系,现在我们就以学生选课的实例来看一看多对多关系映射。由于在多对多映射中,双向多对多用的的比较多,并且单向多对多也比较简单,所以我们就以双向多对多进行讲解

我们先把必要的实体类和实体映射文件写好:

先简单看一下实体类:

student.java

  1. /** 学生实体类 */
  2. public class Student {
  3. private Long id;                //对象标识符(OID)
  4. private String name;            //姓名
  5. private String grade;           //所在班级
  6. private Set<Course> courses;    //所有所选课程的集合
  7. public Student(){}              //无参数的构造方法
  8. ******set、get方法省略
  9. }

Course.java

  1. /** 课程实体类 */
  2. public class Course {
  3. private Long id;                //对象标识符(OID)
  4. private String name;            //课程名
  5. private Double creditHours;     //课时数
  6. private Set<Student> students;  //选择了这门课程的学生的集合
  7. public Course(){}             //无参数的构造方法
  8. ******set、get方法省略
  9. }

下一步编写实体映射文件:

Student.hbm.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  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>
  6. <!-- 映射持久化类 -->
  7. <class name="com.zxf.domain.Student" table="student">
  8. <!-- 映射对象标识符 -->
  9. <id name="id" column="id" type="long">
  10. <generator class="native" />
  11. </id>
  12. <!-- 映射普通属性 -->
  13. <property name="name" />
  14. <property name="grade" />
  15. <!-- 映射集合属性,指定连接表 -->
  16. <set name="courses" table="student_course">
  17. <!-- 用key元素指定本持久类在连接表中的外键字段名 -->
  18. <key column="student_id" />
  19. <!-- 映射多对多关联类 -->
  20. <many-to-many column="course_id"
  21. class="com.zxf.domain.Course" />
  22. </set>
  23. </class>
  24. </hibernate-mapping>
  25. Course.hbm.xml:
  26. <?xml version="1.0" encoding="UTF-8"?>
  27. <!DOCTYPE hibernate-mapping PUBLIC
  28. "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  29. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
  30. <hibernate-mapping>
  31. <!-- 映射持久化类 -->
  32. <class name="com.zxf.domain.Course" table="course">
  33. <!-- 映射对象标识符 -->
  34. <id name="id" column="id" type="long">
  35. <generator class="native" />
  36. </id>
  37. <!-- 映射普通属性 -->
  38. <property name="name" />
  39. <property name="creditHours" column="credit_hours" />
  40. <!-- 映射集合属性,指定连接表 -->
  41. <set name="students" table="student_course" inverse="true">
  42. <!-- 用key元素指定本持久类在连接表中的外键字段名 -->
  43. <key column="course_id" />
  44. <!-- 映射多对多关联类 -->
  45. <many-to-many column="student_id" class="com.zxf.domain.Student" />
  46. </set>
  47. </class>
  48. </hibernate-mapping>

下面具体看一下增删改查的具体测试的关键代码:

增加数据测试:

  1. <span xmlns="http://www.w3.org/1999/xhtml" style=""><span xmlns="http://www.w3.org/1999/xhtml" style="">tran = session.beginTransaction();
  2. Student stu1 = new Student("xiaoli", "two");
  3. Student stu2 = new Student("xiaoming", "two");
  4. Student stu3 = new Student("xiaoqiang", "two");
  5. Course course1 = new Course("java", 3.0);
  6. Course course2 = new Course("c#", 5.0);
  7. //stuset.add(stu1);
  8. //stuset.add(stu2);
  9. //course1.setStudents(stuset);
  10. //session.save(course1);
  11. couset.add(course1);
  12. couset.add(course2);
  13. stu1.setCourses(couset);
  14. session.save(stu1);
  15. tran.commit();</span></span>

测试结论:如果想保存数据成功,不管是主控方还是被控方,如果想通过一次保存即可把双方数据保存,需要把实体配置中的cascade属性设置为all或者save-update,由于设置为all包含delete,在删除数据中,删除一条信息会导致相对应表的多条或者全部信息被删掉,所以一般配置save-update。

Hibernate自身一对多和多对多关系映射的更多相关文章

  1. Java基础-SSM之mybatis一对多和多对一关系映射

    Java基础-SSM之mybatis一对多和多对一关系映射 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.准备测试环境(创建数据库表)  1>.创建customers表: ...

  2. Hibernate中一对多和多对一关系

    1.单向多对一和双向多对一的区别? 只需要从一方获取另一方的数据时 就使用单向关联双方都需要获取对方数据时 就使用双向关系 部门--人员 使用人员时如果只需要获取对应部门信息(user.getdept ...

  3. java框架之Hibernate(3)-一对多和多对多关系操作

    一对多 例:一个班级可以有多个学生,而一个学生只能属于一个班级. 模型 package com.zze.bean; import java.util.HashSet; import java.util ...

  4. hibernate 2 一对多、多对一 双向映射

    多对一或一对多中,在多的一方维护关系效率高 一:java实体类 1.Classes.java package cn.gs.ly.school.entity; import java.util.Set; ...

  5. Spring Boot 入门系列(二十八) JPA 的实体映射关系,一对一,一对多,多对多关系映射!

    前面讲了Spring Boot 使用 JPA,实现JPA 的增.删.改.查的功能,同时也介绍了JPA的一些查询,自定义SQL查询等使用.JPA使用非常简单,功能非常强大的ORM框架,无需任何数据访问层 ...

  6. [Z]Spring Data JPA 之 一对一,一对多,多对多 关系映射

    一.@OneToOne关系映射 JPA使用@OneToOne来标注一对一的关系. 实体 People :用户. 实体 Address:家庭住址. People 和 Address 是一对一的关系. 这 ...

  7. Spring Data JPA 之 一对一,一对多,多对多 关系映射

    一.@OneToOne关系映射 JPA使用@OneToOne来标注一对一的关系. 实体 People :用户. 实体 Address:家庭住址. People 和 Address 是一对一的关系. 这 ...

  8. SpringDataJpa在一对多、多对多关系映射时出现StackOverflowError

    在使用spring-data-jpa时,进行一对多配置后,在调用save方法时,出现内存溢出. 产生原因一:为了方便看信息,在两类中分别重写了 toString 方法,导致查询加载时两类在互相调用对方 ...

  9. EF里一对一、一对多、多对多关系的配置和级联删除

    本章节开始了解EF的各种关系.如果你对EF里实体间的各种关系还不是很熟悉,可以看看我的思路,能帮你更快的理解. I.实体间一对一的关系 添加一个PersonPhoto类,表示用户照片类 /// < ...

随机推荐

  1. GitLab问题小结

    1.内存消耗太大 (1)公司使用gitlab后,发现服务器内存居高不下,使用top命令查看内存消耗,发现服务器上git将近消耗一半内存资源.而且很奇怪的是竟然开启了32个进程.后经查资料,原来这跟gi ...

  2. 2018宁夏邀请赛网赛 I. Reversion Count(java练习题)

    题目链接 :https://nanti.jisuanke.com/t/26217 Description: There is a positive integer X, X's reversion c ...

  3. nginx root&alias 文件路径配置

    nginx 指定文件路径有两种方式 root 和 alias,root 与 alias 主要区别在于 nginx 如何解释 location 后面的 uri,这会使两者分别以不同的方式将请求映射到服务 ...

  4. python3模块: requests

    Python标准库中提供了:urllib等模块以供Http请求,但是,它的 API 太渣了.它是为另一个时代.另一个互联网所创建的.它需要巨量的工作,甚至包括各种方法覆盖,来完成最简单的任务. 发送G ...

  5. web socket 入门

    WebSocket是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议,其优雅地解决了以往web服务器不能向web客户端实时推送消息的问题. 在浏览器js环境中,创建一个websock ...

  6. 【disruptor】1、关于disruptor中的SequenceBarrier对象

    首先这个类的uml结构在disruptor中是这样的,里面只有部分的属性对象和函数内容,具体有什么作用,用到了再说,用不到我也不会... 1.那么这个对象有什么用呢? 注意我们这个类中有哪些属性: 我 ...

  7. java ant 编译打包build.xml完整配置范例

    java ant 编译打包build.xml完整配置范例 <?xml version="1.0" encoding="UTF-8" ?> <p ...

  8. 课程一(Neural Networks and Deep Learning),第四周(Deep Neural Networks)—— 1.Practice Questions: Key concepts on Deep Neural Networks

    [解释] [解释] 比如算法中的learing rateα(学习率).iterations(梯度下降法循环的数量).L(隐藏层数目).n[l] (隐藏层单元数目).choice of activati ...

  9. SpringBoot + docker + neo4j

    下拉镜像 docker pull neo4j 启动镜像 docker run -d -p 7473:7473 -p 7687:7687 -p 7474:7474 neo4j 打开浏览器:http:// ...

  10. scala-02-数组的操作

    scala中的数组和 java中的数组一样, 定义了长度后不可改变 1, 产生一个数组: 有3种创建数组的方式, 分别直接new, 直接赋值, 或者使用 Array中的rang来产生 /** * 获取 ...