一对多关系映射大家都明白,关系双方都一个含有对方多个引用,但自身一对多很多同学都不明白什么意思,那么首先我就说明一下什么是自身一对多,其实也很好理解,自身一对多就是自身含有本身的多个引用,例如新闻类别,新闻包含体育新闻和政治新闻,体育新闻内有含有足球新闻和篮球新闻,其实他们都属于新闻,只是名字不同而已,下面我们就以新闻类别为例来具体说明一下:
首先我们来看一下新闻类别的类图:
类图:category
从上面的图我们可以看出:每一个新闻类别都有一个父类别和一个孩子类别的set集合,这个父类别和孩子类别里面都是自身的引用,这样就行了自身一对多的对象关系
下面看一下具体的新闻实体类:Category.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | public class Category{ private Long id; private String name; private Category parentCategory; private Set<Category> childCategories; public Category(String name, Category parentCategory, Set<Category> childCategories){ this.name = name; this.parentCategory = parentCategory; this.childCategories = childCategories; } public Category(){ } *******set、get方法省略 } |
看完具体的实体类之后我们下面看一下其具体的配置,其实他的配置中没什么特别的地方,仅仅只是他的配置中包含了一对多和多对一的共同标签存在而已:他即含有多的一方的<set>标签。也含有一的一方的<many-to-one>标签:
Category.hbm.xml配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.shengsiyuan.hibernate.Category" table="categories"> <id name="id" column="id" type="long"> <generator class="increment"></generator> </id> <property name="name" type="string" > <column name="name" length="50" ></column> </property> <set name="childCategories" cascade="all" inverse="true"> <key column="category_id"></key> <one-to-many class="com.shengsiyuan.hibernate.Category"/> </set> <many-to-one name="parentCategory" column="category_id" class="com.shengsiyuan.hibernate.Category"> </many-to-one> </class> </hibernate-mapping> |
在很多实际开发过程中,多对多的映射关系也是比较常见的,最为明显的例子就是我们常用的学生选课示例,一个学生可以选多门课,一门课也可以由多个学生去选,这样就形成了多对多的映射关系,现在我们就以学生选课的实例来看一看多对多关系映射。由于在多对多映射中,双向多对多用的的比较多,并且单向多对多也比较简单,所以我们就以双向多对多进行讲解
我们先把必要的实体类和实体映射文件写好:
先简单看一下实体类:
student.java
1 2 3 4 5 6 7 8 9 10 |
Course.java
1 2 3 4 5 6 7 8 9 10 |
StuCourse.java
1 2 3 4 5 6 7 8 9 |
下一步编写实体映射文件:
Student.hbm.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.hsp.domain"> <class name="Student"> <id name="id" type="java.lang.Integer"> <generator class="sequence"> <param name="sequence">stu_seq</param> </generator> </id> <property name="name" type="java.lang.String"> <column name="name" length="64"/> </property> <!-- 这里我们配置了one-to-many 一个学生可以对应多个选课记录 --> <set name="stuCourses"> <key column="student_id"/> <one-to-many class="StuCourse"/> </set> </class> </hibernate-mapping> |
Course.hbm.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.hsp.domain"> <class name="Course"> <id name="id" type="java.lang.Integer"> <generator class="sequence"> <param name="sequence">course_seq</param> </generator> </id> <property name="name" type="java.lang.String"> <column name="name" length="64"/> </property> <!-- 配置one-to-many 表示一门课程可以对应多个选课记录 --> <set name="stuCourses"> <key column="course_id"/> <one-to-many class="StuCourse"/> </set> </class> </hibernate-mapping> |
StuCourse.hbm.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.hsp.domain"> <class name="StuCourse" > <id name="id" type="java.lang.Integer"> <generator class="sequence"> <param name="sequence">stucourse_seq</param> </generator> </id> <property name="grade" type="java.lang.Integer"> <column name="grade" length="3"/> </property> <many-to-one name="course" column="course_id"/> <many-to-one name="student" column="student_id"/> </class> </hibernate-mapping> |
关系图:
下面具体看一下的具体测试的关键代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | package com.hsp.view; import java.util.Date; import java.util.HashSet; import java.util.Set; import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.Transaction; import com.hsp.domain.Course; import com.hsp.domain.StuCourse; import com.hsp.domain.Student; import com.hsp.util.HibernateUtil; public class TestMain { /** * @param args */ public static void main(String[] args) { //添加一组Person/idcard Session s=null; Transaction tx=null; try { //我们使用基础模板来讲解. s=HibernateUtil.getCurrentSession(); tx=s.beginTransaction(); //添加一个学生,一门课程,选课 Student stu1=new Student(); stu1.setName("小明"); Course course=new Course(); course.setName("java"); StuCourse sc=new StuCourse(); sc.setCourse(course); sc.setStudent(stu1); //顺序保存. s.save(stu1); s.save(course); s.save(sc); tx.commit(); } catch (Exception e) { e.printStackTrace(); if(tx!=null){ tx.rollback(); } }finally{ if(s!=null && s.isOpen()){ s.close(); } } } } |
测试结论:如果想保存数据成功,不管是主控方还是被控方,如果想通过一次保存即可把双方数据保存,需要把实体配置中的cascade属性设置为all或者save-update,由于设置为all包含delete,在删除数据中,删除一条信息会导致相对应表的多条或者全部信息被删掉,所以一般配置save-update。
除非注明,Coder文章均为原创,转载请以链接形式标明本文地址