Java程式員從笨鳥到菜鳥之(五十六)細談Hibernate(七)Hibernate自身一對多和多對多關係映射

來源:互聯網
上載者:User

 

  歡迎閱讀本專題其他部落格:     

 

                                  細談Hibernate(十)hibernate查詢排序和組件映射


                                  細談Hibernate(十一)hibernate複合主鍵映射


                                 細談Hibernate(十二)hibernate查詢排序組件映射
                               
細談Hibernate(十三)session緩衝機制和三種對象狀態

       一對多關聯性映射大家都明白,關係雙方都一個含有對方多個引用,但自身一對多很多同學都不明白什麼意思,那麼首先我就說明一下什麼是自身一對多,其實也很好理解,自身一對多就是自身含有本身的多個引用,例如新聞類別,新聞包含體育新聞和政治新聞,體育新聞內有含有足球新聞和籃球新聞,其實他們都屬於新聞,只是名字不同而已,下面我們就以新聞類別為例來具體說明一下:

首先我們來看一下新聞類別的類圖:

類圖:category

                            

       從上面的圖我們可以看出:每一個新聞類別都有一個父系類別和一個孩子類別的set集合,這個父系類別和孩子類別裡面都是自身的引用,這樣就行了自身一對多的對象關係

 

下面看一下具體的新聞實體類:Category.java

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設定檔

<?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>

下面我們來看一下在自身一對多的關係下進行增刪改查的樣本:

import java.util.HashSet;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.Transaction;import org.hibernate.cfg.Configuration;public class HibernateTest2{private static SessionFactory sessionFactory;static{try{sessionFactory = new Configuration().configure().buildSessionFactory();}catch (Exception ex){ex.printStackTrace();}}public static void main(String[] args){Session session = sessionFactory.openSession();Transaction tx = null;try{tx = session.beginTransaction();Category category1 = new Category("level1", null, new HashSet<Category>());Category category2 = new Category("level2", null, new HashSet<Category>());Category category3 = new Category("level2", null, new HashSet<Category>());Category category4 = new Category("level3", null, new HashSet<Category>());Category category5 = new Category("level3", null, new HashSet<Category>());Category category6 = new Category("level3", null, new HashSet<Category>());Category category7 = new Category("level3", null, new HashSet<Category>());category2.setParentCategory(category1);category3.setParentCategory(category1);category1.getChildCategories().add(category2);category1.getChildCategories().add(category3);category4.setParentCategory(category2);category5.setParentCategory(category2);category2.getChildCategories().add(category4);category2.getChildCategories().add(category5);category6.setParentCategory(category3);category7.setParentCategory(category3);category3.getChildCategories().add(category6);category3.getChildCategories().add(category7);Category category = (Category)session.get(Category.class, new Long(1));System.out.println(category.getChildCategories().iterator().next().getName());session.delete(category);tx.commit();}catch(Exception ex){if(null != tx){tx.rollback();}}finally{session.close();}}} 

  

       在很多實際開發過程中,多對多的映射關係也是比較常見的,最為明顯的例子就是我們常用的學生選課樣本,一個學生可以選多門課,一門課也可以由多個學生去選,這樣就形成了多對多的映射關係,現在我們就以學生選課的執行個體來看一看多對多關係映射。由於在多對多映射中,雙向多對多用的的比較多,並且單向多對多也比較簡單,所以我們就以雙向多對多進行講解

      我們先把必要的實體類和實體對應檔寫好:

先簡單看一下實體類:

student.java

/** 學生實體類 */public class Student {private Long id;                //物件識別碼(OID)private String name;            //姓名private String grade;           //所在班級private Set<Course> courses;    //所有所選課程的集合public Student(){}              //無參數的構造方法******set、get方法省略}

 

Course.java

/** 課程實體類 */public class Course {private Long id;                //物件識別碼(OID)private String name;            //課程名private Double creditHours;     //課時數private Set<Student> students;  //選擇了這門課程的學生的集合public Course(){}             //無參數的構造方法******set、get方法省略}

下一步編寫實體對應檔:

Student.hbm.xml

<?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>  <!-- 映射持久化類 --><class name="com.zxf.domain.Student" table="student"><!-- 映射物件識別碼 --><id name="id" column="id" type="long"><generator class="native" /></id><!-- 映射普通屬性 --><property name="name" /><property name="grade" /><!-- 映射集合屬性,指定串連表 --><set name="courses" table="student_course"><!-- 用key元素指定本持久類在串連表中的外鍵欄位名 --><key column="student_id" /><!-- 映射多對多關聯類別 -->      <many-to-many column="course_id"        class="com.zxf.domain.Course" /></set></class></hibernate-mapping>Course.hbm.xml:<?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><!-- 映射持久化類 --><class name="com.zxf.domain.Course" table="course"><!-- 映射物件識別碼 --><id name="id" column="id" type="long"><generator class="native" /></id><!-- 映射普通屬性 --><property name="name" /><property name="creditHours" column="credit_hours" /><!-- 映射集合屬性,指定串連表 --><set name="students" table="student_course" inverse="true"><!-- 用key元素指定本持久類在串連表中的外鍵欄位名 --><key column="course_id" /><!-- 映射多對多關聯類別 --><many-to-many column="student_id" class="com.zxf.domain.Student" /></set></class></hibernate-mapping>

下面具體看一下增刪改查的具體測試的關鍵代碼:

增加資料測試:

           

tran = session.beginTransaction();Student stu1 = new Student("xiaoli", "two");Student stu2 = new Student("xiaoming", "two");Student stu3 = new Student("xiaoqiang", "two");Course course1 = new Course("java", 3.0);Course course2 = new Course("c#", 5.0);//stuset.add(stu1);//stuset.add(stu2);//course1.setStudents(stuset);//session.save(course1);couset.add(course1);couset.add(course2);stu1.setCourses(couset);session.save(stu1);tran.commit();


測試結論:如果想儲存資料成功,不管是主控方還是被控方,如果想通過一次儲存即可把雙方資料儲存,需要把實體配置中的cascade屬性設定為all或者save-update,由於設定為all包含delete,在刪除資料中,刪除一條資訊會導致相對應表的多條或者全部資訊被刪掉,所以一般配置save-update。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.