1. 程式人生 > >Hibernate多對一、雙向關係、控制反轉、級聯配置

Hibernate多對一、雙向關係、控制反轉、級聯配置

Hibernate多對一關係配置

Students配置檔案:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated May 24, 2016 4:29:13 PM by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
	<class name="Students" table="STUDENTS">
		<id name="sid" type="int">
			<column name="SID" />
			<generator class="increment" />
		</id>
		<property name="Sname" type="java.lang.String">
			<column name="SNAME" />
		</property>
		<property name="gender" type="java.lang.String">
			<column name="GENDER" />
		</property>

		<many-to-one name="grade" class="com.yonyou.hibernateentity.Grade"
			column="GID"></many-to-one>
	</class>
</hibernate-mapping>

Student類,持有一個班級類Grade,原始碼請參考 Hibernate 單向一對多配置以及增刪改查,但是班級類沒有持有一個學生集合。
public class Students {
	private int sid;
	private String Sname;
	private String gender;
	private Grade grade;

	public Students() {
	}

	public Students(int sid, String sname, String gender) {
		super();
		this.sid = sid;
		Sname = sname;
		this.gender = gender;
	}
	

	public Students(String sname, String gender) {
		super();
		Sname = sname;
		this.gender = gender;
	}

	public int getSid() {
		return sid;
	}

	public void setSid(int sid) {
		this.sid = sid;
	}

	public String getSname() {
		return Sname;
	}

	public void setSname(String sname) {
		Sname = sname;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	@Override
	public String toString() {
		return "Students [sid=" + sid + ", Sname=" + Sname + ", gender="
				+ gender + "]";
	}

	public Grade getGrade() {
		return grade;
	}

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

	
}

測試程式碼:

<span style="white-space:pre">	</span>@Test
	public void testAdd() {
		Grade grade = new Grade("java一班", "java軟體一班");
		Students stu = new Students("張三", "男");
		Students stu2 = new Students("李四", "女");
		//設定關聯關係
		stu.setGrade(grade);
		stu2.setGrade(grade);
		Session session = HibernateUtil.getSession();
		Transaction transaction = session.beginTransaction();
		session.save(grade);
		session.save(stu);
		session.save(stu2);
		transaction.commit();
		HibernateUtil.closeSession(session);

	}
測試輸出的sql,由於使用的主鍵策略是increment,看出來多方維護需要傳送3個sql語句。
Hibernate: select max(GID) from GRADE
Hibernate: select max(SID) from STUDENTS
Hibernate: insert into GRADE (GNAME, GDESC, GID) values (?, ?, ?)
Hibernate: insert into STUDENTS (SNAME, GENDER, GID, SID) values (?, ?, ?, ?)
Hibernate: insert into STUDENTS (SNAME, GENDER, GID, SID) values (?, ?, ?, ?)
雙向關係配置:需要在grade類加入一個set集合,存放students,grade配置參考 Hibernate 單向一對多配置以及增刪改查

測試程式碼:

@Test
	public void testAdd() {
		Grade grade = new Grade("java一班", "java軟體一班");
		Students stu = new Students("張三", "男");
		Students stu2 = new Students("李四", "女");
		// 設定關聯關係
		grade.getSet().add(stu);
		grade.getSet().add(stu2);
		 stu.setGrade(grade);
		 stu2.setGrade(grade);
		Session session = HibernateUtil.getSession();
		Transaction transaction = session.beginTransaction();
		session.save(grade);
		 session.save(stu);
		 session.save(stu2);
		transaction.commit();
		HibernateUtil.closeSession(session);

	}

測試結果:傳送了兩條更新語句,效率不高。使用控制反轉,由多端控制一端。減少sql語句傳送。
<pre name="code" class="sql">Hibernate: select max(GID) from GRADE
Hibernate: select max(SID) from STUDENTS
Hibernate: insert into GRADE (GNAME, GDESC, GID) values (?, ?, ?)
Hibernate: insert into STUDENTS (SNAME, GENDER, GID, SID) values (?, ?, ?, ?)
Hibernate: insert into STUDENTS (SNAME, GENDER, GID, SID) values (?, ?, ?, ?)
Hibernate: update STUDENTS set GID=? where SID=?Hibernate: update STUDENTS set GID=? where SID=? 在one方,控制反轉 inverse=‘true’,測試結果:
Hibernate: select max(GID) from GRADE
Hibernate: select max(SID) from STUDENTS
Hibernate: insert into GRADE (GNAME, GDESC, GID) values (?, ?, ?)
Hibernate: insert into STUDENTS (SNAME, GENDER, GID, SID) values (?, ?, ?, ?)
Hibernate: insert into STUDENTS (SNAME, GENDER, GID, SID) values (?, ?, ?, ?)

級聯控制,級聯包括 all,save-update,delete,none 預設為none

all,級聯更新插入刪除

save-update 更新,插入級聯

delete級聯刪除

級聯操作

 一.簡單的介紹

cascade和inverse (Employee – Department)

l  Casade用來說明當對主物件進行某種操作時是否對其關聯的從物件也作類似的操作,常用的cascade:

         none,all,save-update,delete, lock,refresh,evict,replicate,persist,

         merge,delete-orphan(one-to-many)。一般對many-to-one,many-to-many不設定級聯,在<one-to-one>和<one-to-many>中設定級聯。

l  inverse表“是否放棄維護關聯關係”(在Java裡兩個物件產生關聯時,對資料庫表的影響),在one-to-many和many-to-many的集合定義中使用,inverse=”true”表示該物件不維護關聯關係;該屬性的值一般在使用有序集合時設定成false(注意hibernate的預設值是false)。

         one-to-many維護關聯關係就是更新外來鍵。many-to-many維護關聯關係就是在中間表增減記錄。

         注: 配置成one-to-one的物件不維護關聯關係

二,屬性的解析
class元素的lazy屬性設定為true,表示延遲載入,如果lazy設為false,則
表示立即載入。以下對這二點進行說明。
     立即載入:表示Hibernate在從資料庫中取得資料組裝好一個物件(如學生1)後,
            會立即再從資料庫取得資料組裝此物件所關聯的物件(如學生證1)。
     延遲載入:表示Hibernate在從資料庫中取得資料組裝好一個物件(如學生1)後,
            不會立即再從資料庫中取得資料組裝此物件所關聯的物件(如學生1),
            而是等到需要時,才會從資料庫取得資料組裝此關聯物件。
<one-to-one>元素的cascade屬性表明操作是否從父物件級聯到被關聯的物件,     它
的取得可以是以下幾種:
     none:在儲存,刪除或修改當前物件時,不對其附屬物件(關聯物件)進行級聯
          操作。它是預設值。
     save-update:在儲存,更新當前物件時,級聯儲存,更新附屬物件(臨時物件,
          遊離物件)。
     delete:在刪除當前物件時,級聯刪除附屬物件。
     all:所有情況下均進行級聯操作,即包含save-update和delete操作。
     delete-orphan:刪除和當前物件解除關係的附屬物件。
<one-to-one>元素的fetch屬性的可選值是join和select,預設是select。
當fetch屬性設定為join時,表示連線抓取(Join fetching):Hibernate通過
在Select語句中使用outer join(外連線)來獲得物件的關聯例項或者關聯集合。
當fetch屬性設定為select時,表示查詢抓取(Select fetching):需要另外發
送一條Select語句抓取當前物件的關聯實體或集合。

三。程式碼練習

<set name="emps" cascade="save-update">
 <key column="depart_id"/>
  <one-to-many class="Employee"/>
</set>

<set name="students" table="taacher_student" inverse="true"><!-- table是用來指定中間表的屬性 -->
<key column="teacher_id"></key><!-- 查詢教師id時,連結中間表表的teacher_id -->
<many-to-many class="Student" column="student_id"></many-to-many>
</set>