<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 89,  comments - 98,  trackbacks - 0
    在前一篇文章《使用Hibernate來實現持久對象》中,介紹了Hibernate的基本概念,然后用實例演示了怎么在Web應用中使用Hibernate來封裝持久數據對象。然而在現實的項目中,我們往往需要操作多個數據表,并且多個表之間往往存在復雜的關系,在本文,將介紹怎么在Hibernate中描述多個表的映射關系,并且演示怎么操作關系復雜的持久對象。

      本文的全部代碼在這里下載

      案例介紹

      在第一篇文章中,我們對一個表進行了簡單的封裝。在這篇文章中,我們討論更加復雜的情況。

      在這個例子中,將考慮到表之間的一對一、一對多、多對多的情況。如圖1所示。


    圖1 實體之間的映射關系

      在上面的數據模型圖中,Student是所有表的核心,它和Classes表是一對多的關系,和Course表是多對多的關系(通過Student_Course_Link表來鏈接),和Address表是一對一的關系。

      通過分析,我們可以把上面的數據模型轉換成如下的Java持久對象,如圖2所示。


    圖2 持久對象之間的關系

      可以看出,數據模型圖和Java持久對象的類圖有非常大的相似性,但是不完全相同。比如Classes表和Student表是一對多的關系;在類圖中,兩者仍然是一對多的關系,但是在Classes類中添加了一個student屬性,屬性的類型是java.util.Set,它表示Classes對象中包含的所有Student對象。

      創建Hibernate持久對象

      已經對數據模型經過了分析,現在就可以創建持久對象了。持久對象之間的關系由圖2所示的類圖指定。

      我們首先來看Student類,它是這個關系映射的核心,代碼如例程1所示。

      例程1 Student持久對象(Student.java)

    package com.hellking.study.hibernate;

    import java.util.Set;
    /**
    ?*在hibernate中代表了Students表的類。
    ?*/
    public class Student
    {
    ?? /**屬性,和students表中的字段對應**/
    ?? private String id;
    ?? private String name;
    ?? /**和其它類之間的映射關系**/
    ?? private Set courses;
    ?? private Classes classes;
    ?? private Address address;
    ??
    ?? ?/**屬性的訪問方法,必須是公共的方法**/
    ?? ?public void setId(String string) {
    ??id = string;
    ?}
    ?
    ?public String getId() {
    ??return id;
    ?}
    ?
    ?public void setName(String name)
    ?{
    ??this.name=name;
    ?}
    ?public String getName()
    ?{
    ??return this.name;
    ?}
    ?
    ?/**操作和其它對象之間的關系**/
    ?public void setCourses(Set co)
    ?{
    ??this.courses=co;
    ?}
    ?public Set getCourses()
    ?{
    ??return this.courses;
    ?}
    ?public void setAddress(Address ad)
    ?{
    ??this.address=address;
    ?}
    ?public Address getAddress()
    ?{
    ??return this.address;
    ?}
    ?public void setClasses(Classes c)
    ?{
    ??this.classes=c;
    ?}
    ?public Classes getClasses()
    ?{
    ??return this.classes;
    ?}??
    }

      在Student類中,由于Students表和Classes的表是多對一的關系,故它包含了一個類型為Classes的classes屬性,它的實際意義是一個學生可以有一個班級;Students表和Address的表是一對一的關系,同樣也包含了一個類型為Address的address屬性,它的實際意義是一個學生有一個地址;Students表和Course是多對多的關系,故它包含了一個類型為java.util.Set的course屬性,它的實際意義是一個學生可以學習多門課程,同樣,某個課程可以由多個學生來選修。

      Classes對象和Student對象是一對多的關系。Classes對象包含一個類型為java.util.Set的students屬性,它的代碼如例程2所示。

      例程2 Classes持久對象(Classes.java)

    package com.hellking.study.hibernate;

    import java.util.Set;
    /**
    ?*在hibernate中代表了Classes表的類。
    ?*/
    public class Classes
    {
    ?? /**屬性,和classes表的字段一致**/
    ?? private String id;?
    ?? private String name;
    ?? /**和其它類之間的映射關系**/
    ?? private Set students;
    ??
    ?? /**屬性的訪問方法,必須是公共的方法**/
    ?? public void setId(String string) {
    ??id = string;
    ?}
    ?
    ?public String getId() {
    ??return id;
    ?}
    ?
    ?public void setName(String name)
    ?{
    ??this.name=name;
    ?}
    ?public String getName()
    ?{
    ??return this.name;
    ?}
    ?
    ?/**操作和其它對象之間的關系**/
    ?public void setStudents(Set stud)
    ?{
    ??this.students=stud;
    ?}
    ?public Set getStudents()
    ?{
    ??return this.students;
    ?}
    }

      Course持久對象在前一篇文章已經介紹,在這里就不再列舉。Address持久對象比較簡單,除了表字段定義的屬性外,沒有引入其它的屬性,請參考本文的代碼。

      描述對象之間的關系

      現在我們已經編寫好了持久對象,下面的任務就是描述它們之間的關系。首先我們看Student持久對象的描述,如例程3所示。

      例程3 Student持久對象的描述(Student.hbm.xml)

    <?xml version="1.0"?>

    <!DOCTYPE hibernate-mapping PUBLIC
    ??? "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
    ??? "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

    <hibernate-mapping>
    ??? <class
    ??????? name="com.hellking.study.hibernate.Student"
    ??????? table="Students"
    ??????? dynamic-update="false"
    ??? >
    ?? <!-- 描述ID字段-->
    ??????? <id
    ??????????? name="id"
    ??????????? column="StudentId"
    ??????????? type="string"
    ??????????? unsaved-value="any"
    ??????? >
    ??????????? <generator class="assigned"/>
    ??????? </id>
    ???? <!-- 屬性-->
    ???????? <property
    ??????????? name="name"
    ??????????? type="string"
    ??????????? update="true"
    ??????????? insert="true"
    ??????????? column="Name"
    ??????? />
    <!-- 描述Student和Course多對多的關系-->
    ???????? <set
    ??????????? name="courses"
    ??????????? table="Student_Course_Link"
    ??????????? lazy="false"
    ??????????? inverse="false"
    ??????????? cascade="all"
    ??????????? sort="unsorted"
    ??????? >

    ????????????? <key
    ????????????????? column="StudentId"
    ????????????? />

    ????????????? <many-to-many
    ????????????????? class="com.hellking.study.hibernate.Course"
    ????????????????? column="CourseId"
    ????????????????? outer-join="auto"
    ????????????? />
    ??????? </set>
    <!-- 描述Student和Classes之間多對一的關系-->
    ????????? <many-to-one
    ??????????? name="classes"
    ??????????? class="com.hellking.study.hibernate.Classes"
    ??????????? cascade="none"
    ??????????? outer-join="auto"
    ??????????? update="true"
    ??????????? insert="true"
    ??????????? column="ClassesId"
    ??????? />
    ???????
    <!-- 描述Student和Address之間一對一的關系-->???????
    ?<one-to-one
    ??????????? name="address"
    ??????????? class="com.hellking.study.hibernate.Address"
    ??????????? cascade="none"
    ??????????? outer-join="auto"
    ??????????? constrained="false"
    ??????? />??????
    ??? </class>
    </hibernate-mapping>

      在Student.hbm.xml描述符中,共描述了三種關系。第一種是Student和Address之間一對一的關系,它是最簡單的關系,使用:

      <one-to-one name="" class="">

      來描述,這里的name表示的是Student對象中名稱為address的屬性;class表示的是address屬性的類型:com.hellking.study.hibernate.Address。

      接下來看Student和Classes之間多對一的關系,使用:

      <many-to-one?? name="classes" class="com.hellking.study.hibernate.Classes" column="ClassesId" …?? />

      來描述。同樣,name表示的是Student對象中名稱為classes的屬性;class表示的是classes屬性的類型,column表示Student表引用Classes表使用的外部鍵名稱。對應的,在Classes類中也引用了Student類,它使用了以下的描述符來描述這個關系:

    ??????? <set
    ??????????? name="students"
    ??????????? table="Students"
    ??????????? lazy="false"
    ??????????? inverse="false"
    ??????????? cascade="all"
    ??????????? sort="unsorted"
    ??????? >
    ????????????? <key
    ????????????????? column="ClassesId"
    ????????????? />

    ????????????? <one-to-many
    ????????????????? class="com.hellking.study.hibernate.Student"
    ????????????? />
    ??????? </set>

      在描述Student和Course之間多對多關系時,使用了以下的方法:

    ??????? <set
    ??????????? name="courses"
    ??????????? table="Student_Course_Link"
    ??????????? lazy="false"
    ??????????? inverse="false"
    ??????????? cascade="all"
    ??????????? sort="unsorted"
    ??????? >
    ????????????? <key
    ????????????????? column="StudentId"
    ????????????? />
    ????????????? <many-to-many
    ????????????????? class="com.hellking.study.hibernate.Course"
    ????????????????? column="CourseId"
    ????????????????? outer-join="auto"
    ????????????? />
    ??????? </set>

      在映射多對多關系時,需要另外使用一個鏈接表,這個表的名字由table屬性指定,鏈接表包含了兩個字段:CourseId和StudentId。以下的描述:

      <key column="StudentId">

      指定了Student對象在Student_Course_Link鏈接表中的外部鍵。對應的,在Course持久對象使用了以下的描述符來描述這個關系:

    ??????? <set
    ??????????? name="students"
    ??????????? table="Student_Course_Link"
    ??????????? lazy="false"
    ??????????? inverse="false"
    ??????????? cascade="all"
    ??????????? sort="unsorted"
    ??????? >
    ????????????? <key
    ????????????????? column="CourseId"
    ????????????? />

    ????????????? <many-to-many
    ????????????????? class="com.hellking.study.hibernate.Student"
    ????????????????? column="StudentId"
    ????????????????? outer-join="auto"
    ????????????? />
    ??????? </set>

      由于其它持久對象的描述基本一樣,在這里就不一一列舉了,請參考本文的源代碼。最后別忘了在hibernate.cfg.xml里增加這幾個對象的描述。

    ??????? <!-- Mapping files -->
    ??????? <mapping resource="Address.hbm.xml"/>
    ??????? <mapping resource="Student.hbm.xml"/>
    ??????? <mapping resource="Classes.hbm.xml"/>
    ??????? <mapping resource="Course.hbm.xml"/

      使用映射關系

      下面我們開發一個簡單的實例來測試這個映射。持久對象使用最頻繁的操作是增加數據、查詢數據、刪除數據、更新數據。對于更新數據的操作的情況,多個表的操作和單個表沒有兩樣,在這里不舉例了。

      添加數據到數據庫

      我們在這里測試前三種操作,首先來看添加數據到數據庫的情況,如例程4所示。

      例程4 測試持久對象之間的映射關系之添加數據(MapTestBean.java部分代碼)

    ??/**
    ? *在數據庫中添加數據
    ? */
    ? public void addData(String studentId,String classesId,String coursesId)
    ??????? throws HibernateException {
    ??????? try
    ??????? {
    ????????? /**
    ?????????? *以下的代碼添加了一個Student,同時為Student指定了
    ?????????? *Address、Courses和Classses。
    ?????????? */
    ????????? beginTransaction();?
    ????????? //創建一個Student對象 。??????
    ????????? Student student = new Student();
    ????????? student.setName("hellking2");
    ????????? student.setId(studentId);
    ?????????
    ????????? //創建一個Address對象。
    ????????? Address addr=new Address();
    ????????? addr.setCity("beijing");
    ????????? addr.setState("bj");
    ????????? addr.setStreet("tsinghua");
    ????????? addr.setZip("100083");
    ????????? addr.setId(student.getId());???????
    ???//設置Student和address的關系。
    ????????? student.setAddress(addr);??????
    ????????
    ???????? Set set=new HashSet();
    ???????? set.add(student);
    ???????? //創建一個course對象。
    ???????? Course course=new? Course? ();
    ???????? course.setId(coursesId);
    ???????? course.setName("computer_jsp");
    ???????? //設置course和student對象之間的關系。
    ???????? course.setStudents(set);
    ??????
    ???????? //創建一個classes對象。
    ???????? Classes cl=new Classes();
    ???????? cl.setId(classesId);
    ???????? cl.setName("engine power");
    ???????? //設置某個classes對象包含的students對象。
    ???????? cl.setStudents(set);
    ??????? //由于是雙向的關系,student對象也需要設置一次。
    ???????? student.setClasses(cl);???????
    ????????
    ???????? //保存創建的對象到session中。
    ???????? session.save(cl);
    ???????? session.save(course);
    ???????? session.save(student);
    ???????? session.save(addr);
    ???????? //提交事務,使更改生效。
    ???????? endTransaction(true);
    ?????? }
    ?????? catch(HibernateException e)
    ?????? {????????
    ?????????? System.out.println("在添加數據時出錯!");
    ?????????? e.printStackTrace();
    ?????? ??? throw e;
    ?????? }
    ??? }

      在例程4中,添加數據到數據庫之前,首先設置持久對象的各個屬性,如:

      student.setName("hellking2");

      這種設置屬性的方式和普通的類沒有什么區別,設置完所有的屬性后,就設置持久對象之間的關系,如:

      student.setAddress(addr);

      如果存在對象之間的多重關系,那么可能需要把對象保存在Set集合中,然后再進行設置,如:

      Set set=new HashSet();
      set.add(student);
      course.setStudents(set);

      當設置完所有的屬性和對象關系之后,就可以調用:

      session.save(persistentObject);

      方法把持久對象保存到Hibernate會話中。最后,調用endTransaction來提交事務,并且關閉Hibernate會話。

      數據查詢

      在復雜的實體對象映射中,往往查詢也比較復雜。作為演示,我們在這里也提供了幾個查詢方法,如例程5所示。

      例程5 測試持久對象之間的映射關系之查詢數據(MapTestBean.java部分代碼)

    ??? /**
    ???? *獲得某個給定studentid的Student的地址信息
    ???? */
    ??? public Address getAddress(String id) throws HibernateException
    ??? {??? ?
    ??? ???? beginTransaction();??? ?
    ???? ?Student st=(Student)session.load(Student.class,id);???
    ???? ?Address addr=(Address)session.load(Address.class,st.getId());
    ???? ?endTransaction(false);?
    ???return addr;
    ???
    ??? }
    ???
    ??? /**
    ???? *獲得某個給定studentid的Student的所有課程
    ???? */
    ??? public Set getCourses(String id)throws HibernateException
    ??? {
    ??? ?beginTransaction();??? ?
    ??? ?Student st=(Student)session.load(Student.class,id);
    ???? ?endTransaction(false);???
    ??? ?return st.getCourses();
    ??? }
    ???
    ??? /**
    ???? *測試獲得某個給定studentid的Student所屬的Classes
    ???? */
    ??? public Classes getClasses(String id)throws HibernateException
    ??? {??? ?
    ??? ?beginTransaction();??? ?
    ??? ?Student st=(Student)session.load(Student.class,id);
    ??? ?System.out.println(st.getClasses().getId());?
    ??? ?endTransaction(false);?
    ??? ?return st.getClasses();
    ??? }

      這里提供了三種查詢方法,分別是:

      查詢給定id的Student的Address信息;
      查詢給定id的Student的所有Courses信息;
      查詢給定id的Student所屬的Classes信息。

      在查詢時,首先使用beginTransaction()方法創建一個Hibernate會話對象,并且開始一個新Hibernate事務;然后通過session.load()方法獲得給定ID的Student對象,如:

      Student st=(Student)session.load(Student.class,id);

      最后調用student.getXXX()方法返回指定的對象。

      刪除數據

      在表的關系比較復雜時,要刪除數據,往往存在級聯刪除的情況,由于級聯刪除的情況比較復雜,在這里就不舉例了。假設我們要刪除和某個給定id的student對象的所有相關的記錄,就可以使用例程6所示的方法。

      例程6 測試持久對象之間的映射關系之刪除數據(MapTestBean.java部分代碼)

    ??? /**
    ???? *刪除和某個學生相關的所有信息
    ???? *(這里只是測試,我們暫且不說這種操作的意義何在)。
    ???? */
    ??? public void delteStudent(String id)throws HibernateException
    ??? {
    ??? ?beginTransaction();??? ?
    ??? ?Student st=(Student)session.load(Student.class,id);???? ?
    ??? ?Address addr=(Address)session.load(Address.class,st.getId());
    ??? ?//刪除address信息。
    ??? ?session.delete(addr);
    ??? ?//刪除classes信息。
    ??? ?session.delete(st.getClasses());
    ??? ?/**
    ??? ? *逐個刪除course。
    ??? ? */
    ??????? for(Iterator it=st.getCourses().iterator();it.hasNext();)
    ??????? {
    ??????? ?Course c=(Course)it.next();
    ??????? ?session.delete(c);
    ??????? }
    ??????? //最后,刪除student對象。
    ??? ?session.delete(st);
    ??? ?endTransaction(true);?
    ??? }

      同樣,在執行刪除前,首先使用beginTransaction()方法創建一個新Hibernate會話和一個新Hibernate事務,然后把要刪除的對象Load進來,接下來調用session.delete()方法來刪除指定對象。

      如果要刪除的是集合中的對象,那么可以通過一個迭代來逐個刪除,如例程6中刪除courses的方法。

      測試

      在這里提供了在JSP中調用MapTestBean進行測試的程序,具體代碼見maptest.jsp文件。在進行測試前,請確保連接數據庫的配置完好,并且每個持久對象的配置都沒有錯誤。如果配置出現困難,請參考本文的源代碼。

      行動起來

      經過兩篇文章由淺入深的學習,希望能夠起到拋磚引玉的作用,相信讀者對Hibernate的認識已經有一個整體的把握。Hibernate由于它的易用性和良好的移植性等特點,逐漸在企業級應用開發中廣泛使用。Hibernate官方網站提供了非常好的使用手冊,您可以參考它。如果您并非精通JDBC并且不想學習它,不妨考慮使用Hibernate;如果您在使用實體Bean之類的持久框架遇到困難,也許Hibernate可以助你一臂之力!

    posted on 2006-06-26 09:28 水煮三國 閱讀(152) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    常用鏈接

    留言簿(4)

    隨筆分類(85)

    隨筆檔案(89)

    文章分類(14)

    文章檔案(42)

    收藏夾(37)

    java

    oracle

    Sybase

    搜索

    •  

    積分與排名

    • 積分 - 210901
    • 排名 - 266

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 精品久久久久久亚洲| 日韩精品亚洲专区在线观看| 亚洲精品无码精品mV在线观看| 一级成人生活片免费看| 亚洲国产aⅴ综合网| www永久免费视频| 最新精品亚洲成a人在线观看| 国产男女爽爽爽免费视频| 亚洲欭美日韩颜射在线二| 国产午夜无码精品免费看| 亚洲av片劲爆在线观看| 永久在线免费观看| 亚洲偷自精品三十六区| 深夜国产福利99亚洲视频| 亚洲精品黄色视频在线观看免费资源| 精品亚洲一区二区三区在线播放| 国产精品成人免费观看| 亚洲视频在线观看一区| 野花高清在线电影观看免费视频| 亚洲第一综合天堂另类专| 亚洲福利视频一区二区| 性无码免费一区二区三区在线| 亚洲欧洲视频在线观看| 香蕉视频在线观看免费国产婷婷| 大片免费观看92在线视频线视频 | heyzo亚洲精品日韩| 精品无码一级毛片免费视频观看 | 亚洲一区二区三区91| 好男人视频在线观看免费看片| 美女18毛片免费视频| 亚洲国产精品乱码一区二区| 日韩在线免费视频| 免费看又黄又爽又猛的视频软件| 国精无码欧精品亚洲一区| 成人免费视频88| 国产精品无码永久免费888| 噜噜噜亚洲色成人网站∨| 国产一级特黄高清免费大片| 久久久久国产精品免费免费不卡| 国产精品高清视亚洲一区二区| 亚洲午夜国产精品无码老牛影视 |