接觸Hibernate也有一小段的時間了,愈發的覺得Hibernate是個神奇的東西,為什麼這麼說呢?因為你可以不懂一行sql,直接面向對象,就可以將數據直接保存到資料庫去!! 你還可以保存一個對象,然後一次性的將與它相關的所有數據保存到資料庫,比如說,你只需要保存班級對象,就可以將該班級信息和該班 ...
接觸Hibernate也有一小段的時間了,愈發的覺得Hibernate是個神奇的東西,為什麼這麼說呢?因為你可以不懂一行sql,直接面向對象,就可以將數據直接保存到資料庫去!!
你還可以保存一個對象,然後一次性的將與它相關的所有數據保存到資料庫,比如說,你只需要保存班級對象,就可以將該班級信息和該班級下的所有學生在資料庫中形成一堆的記錄。
而且都不需要你寫sql!!!
有木有很神奇。。。。反正寶寶我是驚呆了。
下麵就拿具體的代碼實現來講吧~
首先講一個簡單的 單向一對多的案例(以班級和學生作為案例)
眾所周知,Hibernate運用的是一種面向對象的思想,我們想要與資料庫相關聯,首先我們得必須有與之相對應的實體類
比如說,我有一個學生對象和班級對象,分別對應資料庫中的學生表和班級表具體信息如下:
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; } }
一對多的話,應該是比較好理解的,因為我們可以理解為 一個班級可以以對應多個學生,這就是一對多,既然一個班級對應多個學生的話,那麼我們是不是就可以在班級的實體類
中加入一個學生集合和呢?這樣是不是更能體現出一對多的關係呢?所以我們對班級實體就有了下麵的改造
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中單向關係映射的知識點了,明天為大家講解關於雙向多對多關係映射的知識點。