詳談Hibernate框架關係映射!

接觸Hibernate也有一小段的時間了,愈發的以爲Hibernate是個神奇的東西,爲何這麼說呢?由於你能夠不懂一行sql,直接面向對象,就能夠將數據直接保存到數據庫去!!java

你還能夠保存一個對象,而後一次性的將與它相關的全部數據保存到數據庫,好比說,你只須要保存班級對象,就能夠將該班級信息和該班級下的全部學生在數據庫中造成一堆的記錄。sql

並且都不須要你寫sql!!!數據庫

有木有很神奇。。。。反正寶寶我是驚呆了。session

下面就拿具體的代碼實現來說吧~app

首先講一個簡單的  單向一對多的案例(以班級和學生做爲案例)測試

衆所周知,Hibernate運用的是一種面向對象的思想,咱們想要與數據庫相關聯,首先咱們得必須有與之相對應的實體類this

好比說,我有一個學生對象和班級對象,分別對應數據庫中的學生表和班級表具體信息以下:spa

package entity;
/*
*學生表 
*/ import java.io.Serializable;
public class Student implements Serializable { private Integer sid;//學生編號 private String sname;//學生姓名 private String sex;//學生性別 public Student() { } public Student(String sname, String sex) { this.sname = sname; this.sex = sex; } public Integer getSid() { return sid; } public void setSid(Integer sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } }

 

package entity;
/*
*班級表
*/
import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Grade implements Serializable {
    private Integer gid;//班級編號
    private String gname;//班級名稱
    private String gdesc;//班級描述
    
    public Grade() {
    }
    
    public Grade(String gname, String gdesc) {
        this.gname = gname;
        this.gdesc = gdesc;
    }

    public Integer getGid() {
        return gid;
    }
    public void setGid(Integer gid) {
        this.gid = gid;
    }
    public String getGname() {
        return gname;
    }
    public void setGname(String gname) {
        this.gname = gname;
    }
    public String getGdesc() {
        return gdesc;
    }
    public void setGdesc(String gdesc) {
        this.gdesc = gdesc;
    }
    
    
}

 

一對多的話,應該是比較好理解的,由於咱們能夠理解爲   一個班級能夠以對應多個學生,這就是一對多,既然一個班級對應多個學生的話,那麼咱們是否是就能夠在班級的實體類hibernate

中加入一個學生集合和呢?這樣是否是更能體現出一對多的關係呢?因此咱們對班級實體就有了下面的改造3d

package entity;

import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Grade implements Serializable {
    private Integer gid;//年級編號
    private String gname;//年級名稱
    private String gdesc;//年級描述
    //添加一個班級裏的學生集合
    private Set<Student> stus=new HashSet<Student>(); public Set<Student> getStus() { return stus; } public void setStus(Set<Student> stus) { this.stus = stus; } public Grade() {
    }
    
    public Grade(String gname, String gdesc) {
        this.gname = gname;
        this.gdesc = gdesc;
    }

    public Integer getGid() {
        return gid;
    }
    public void setGid(Integer gid) {
        this.gid = gid;
    }
    public String getGname() {
        return gname;
    }
    public void setGname(String gname) {
        this.gname = gname;
    }
    public String getGdesc() {
        return gdesc;
    }
    public void setGdesc(String gdesc) {
        this.gdesc = gdesc;
    }
    
    
}

 

實體類寫完了,咱們就該寫最關鍵的配置文件也就是映射文件了(Grade.hbm.xml)

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 對應所在的包 -->
<hibernate-mapping package="entity">
    <!-- 實體類和數據表的名稱 -->
    <class name="Grade" table="Grade">
        <!-- 實體類中和數據表中所對應的主鍵 -->
        <id name="gid" column="gid">
            <!-- 主鍵生成策略  increment是值找到最大的主鍵 值,並加1 -->
            <generator class="increment" />
        </id>
        <!-- 非主鍵屬性的配置 -->
        <property name="gname" column="gname" />
        <property name="gdesc"  column="gdesc"/>
        
        <!-- 配置多對一配置信息   -->
        <set name="stus" table="Student" >
            <!-- 多方的外建值 -->
            <key column="gid"></key>
            <one-to-many class="entity.Student"/>
        </set>
    </class>
</hibernate-mapping>

 

這樣咱們就完成了一對多的配置了,此時,咱們不用對Student.hbm.xml作任何操做,下面能夠測試了

//單向一對多案例(一個班級對應多個學生)
    public static void DOneToManyAdd(){
        //準備session 
        Session session=HibernateUtil.currentSession();
        //開啓事務
        Transaction tx = session.beginTransaction();
        //建立一個班級
        Grade grade=new Grade("S1261","無敵的Y1261班");
        //準備幾個學生
        Student stu1=new Student("微熱的雪","");
        Student stu2=new Student("巴黎的雨季","");
        //設置班級裏的學生
        grade.getStus().add(stu1);
        grade.getStus().add(stu2);
        
        //保存
        session.save(grade);
        session.save(stu1);
        session.save(stu2);
        
        //提交事務
        tx.commit();
        //關閉鏈接
        HibernateUtil.closeSession();
    }

 

執行這些代碼後能夠在控制檯看到以下信息

這個時候,你的數據庫中便有了以下信息

 

能夠從上面的測試代碼中看出,我並無手動的指定學生所在的班級,可是由於有映射文件,Hibernate會自動的檢索到所在的班級並自行的發送sql語句到數據庫進行持久化操做。

這就是Hibernate的強大之處,固然,這只是一個最簡單的例子,下面就跟着我看看更加有趣的例子吧!

 

 Hibernate關係映射二之   單向多對一關係映射

多對一關係映射也一樣的好理解,好比,多個學生能夠同時處於一個班級下,這就是單向的多對一的關係,因此咱們就能夠想到在學生表中加入一個班級屬性

package entity;

import java.io.Serializable;

public class Student implements Serializable {
    private Integer sid;//學生編號
    private String sname;//學生姓名
    private String sex;//學生性別
    //建立一個班級
    private Grade grade;

    public Grade getGrade() {
        return grade;
    }

    public void setGrade(Grade grade) {
        this.grade = grade;
    }

    public Student() {
    }
    
    public Student(String sname, String sex) {
        this.sname = sname;
        this.sex = sex;
    }

    public Integer getSid() {
        return sid;
    }
    public void setSid(Integer sid) {
        this.sid = sid;
    }
    public String getSname() {
        return sname;
    }
    public void setSname(String sname) {
        this.sname = sname;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    
    
}

 

 由於是單向的多對一,因此咱們只須要在多的一方,也就是學生方的配置文件中進行修改,班級方的配置文件保持原始(也就是沒有set標籤的時候)

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="entity">
    <class name="Student" table="Student">
        <id name="sid" column="sid">
            <generator class="increment" />
        </id>
        <property name="sname" column="sname" />
        <property name="sex"  column="sex"/>
        <!-- 配置多對一的關係映射 -->
        <many-to-one name="grade" class="entity.Grade" column="gid"></many-to-one>
    </class>
</hibernate-mapping>

 

一樣,咱們作一個單向多對一的添加操做

//單向多對一添加案例(多個學生對應一個班級)
    public static void DManyToOneAdd(){
        //準備session 
        Session session=HibernateUtil.currentSession();
        //開啓事務
        Transaction tx = session.beginTransaction();
        //建立一個班級
        Grade grade=new Grade("S2222班","挺6的S2222班");
        //準備幾個學生
        Student stu1=new Student("恩恩","");
        Student stu2=new Student("呵呵","");
        //設置學生所在的班級
        stu1.setGrade(grade);
        stu2.setGrade(grade);
        //保存
        session.save(grade);
        session.save(stu1);
        session.save(stu2);
        //提交事務
        tx.commit();
        //關閉鏈接
        HibernateUtil.closeSession();
    }

 

注意!!!此時的Hibernate生成的sql語句與一對多時是不同的!

數據庫中一樣也是有相對應的記錄

 

通過上面兩個案例的展現,可能有同窗就會有疑問了,既然多個學生能夠屬於一個班級,一個班級又能夠有多個學生,那麼他們倆之間到底能夠設爲 什麼關係呢?

此時,咱們就能夠設置爲  雙向的一對多的關係了。由於班級和學生是一個雙向的關係,並且一個班級又有多個學生

這時咱們完整的配置文件就是以上的兩個總和了

Student.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="entity">
    <class name="Student" table="Student">
        <id name="sid" column="sid">
            <generator class="increment" />
        </id>
        <property name="sname" column="sname" />
        <property name="sex"  column="sex"/>
        <!-- 配置多對一的關係映射 -->
        <many-to-one name="grade" class="entity.Grade" column="gid" ></many-to-one>
    </class>
</hibernate-mapping>

 

Grade.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 對應所在的包 -->
<hibernate-mapping package="entity">
    <!-- 實體類和數據表的名稱 -->
    <class name="Grade" table="Grade">
        <!-- 實體類中和數據表中所對應的主鍵 -->
        <id name="gid" column="gid">
            <!-- 主鍵生成策略  increment是值找到最大的主鍵 值,並加1 -->
            <generator class="increment" />
        </id>
        <!-- 非主鍵屬性的配置 -->
        <property name="gname" column="gname" />
        <property name="gdesc"  column="gdesc"/>
        
        <!-- 配置多對一配置信息   -->
        <set name="stus" table="Student"  >
            <!-- 多方的外建值 -->
            <key column="gid"></key>
            <one-to-many class="entity.Student"/>
        </set>
    </class>
</hibernate-mapping>

 

測試數據

//雙向添加案例
    private static void SAdd(){
        //準備session 
        Session session=HibernateUtil.currentSession();
        //開啓事務
        Transaction tx = session.beginTransaction();
        //建立一個班級
        Grade grade=new Grade("S2222班","挺6的S2222班");
        //準備幾個學生
        Student stu1=new Student("巴黎的雨季","");
        Student stu2=new Student("微熱的雪","");
        //設置班級下的學生
        grade.getStus().add(stu1);
        grade.getStus().add(stu2);
        //爲學生設置班級
        stu1.setGrade(grade);
        stu2.setGrade(grade);
        //保存
        session.save(grade);
            session.save(stu1);
        session.save(stu2);
        //提交事務
        tx.commit();
        
        //關閉鏈接
        HibernateUtil.closeSession();
    }

 

細心的同窗會發現,當我執行了上面的代碼時,效果與我設置多對一和一對多的效果同樣,並且這還比較的繁瑣和複雜,因此這並非雙向關係的優點

這裏咱們就要用到cascade(級聯)的屬性了   設置級聯的屬性後,由於有 雙向的關係,因此當你只添加班級的時候Hibernate會自動的添加班級下的學生

Student.hbm.xml

 

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="entity">
    <class name="Student" table="Student">
        <id name="sid" column="sid">
            <generator class="increment" />
        </id>
        <property name="sname" column="sname" />
        <property name="sex"  column="sex"/>
        <!-- 配置多對一的關係映射 -->
        <many-to-one name="grade" class="entity.Grade" column="gid" cascade="all"></many-to-one>
    </class>
</hibernate-mapping>

 

Grade.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 對應所在的包 -->
<hibernate-mapping package="entity">
    <!-- 實體類和數據表的名稱 -->
    <class name="Grade" table="Grade">
        <!-- 實體類中和數據表中所對應的主鍵 -->
        <id name="gid" column="gid">
            <!-- 主鍵生成策略  increment是值找到最大的主鍵 值,並加1 -->
            <generator class="increment" />
        </id>
        <!-- 非主鍵屬性的配置 -->
        <property name="gname" column="gname" />
        <property name="gdesc"  column="gdesc"/>
        
        <!-- 配置多對一配置信息   -->
        <set name="stus" table="Student" cascade="all" inverse="true">
            <!-- 多方的外建值 -->
            <key column="gid"></key>
            <one-to-many class="entity.Student"/>
        </set>
    </class>
</hibernate-mapping>

 

 這樣當咱們設置級聯的屬性後,測試代碼以下

//雙向添加案例(添加班級自動添加班級下的學生)
    private static void SAdd(){
        //準備session 
        Session session=HibernateUtil.currentSession();
        //開啓事務
        Transaction tx = session.beginTransaction();
        //建立一個班級
        Grade grade=new Grade("S2222班","挺6的S2222班");
        //準備幾個學生
        Student stu1=new Student("巴黎的雨季","");
        Student stu2=new Student("微熱的雪","");
        //設置班級下的學生
        grade.getStus().add(stu1);
        grade.getStus().add(stu2);
        //爲學生設置班級
        stu1.setGrade(grade);
        stu2.setGrade(grade);
        //保存(設置級聯屬性,自動關聯該班級下的學生)
        session.save(grade);
    
        
        //提交事務
        tx.commit();
        
        //關閉鏈接
        HibernateUtil.closeSession();
    }

 

這樣,咱們只用寫save(grade) 保存班級,這時Hibernate會生成以下代碼

至此,基本上就講完了Hibernate中單向關係映射的知識點了,明天爲你們講解關於雙向多對多關係映射的知識點。

相關文章
相關標籤/搜索