1. 程式人生 > >Hibernate(5.3.7)關聯關係中的反轉和級聯

Hibernate(5.3.7)關聯關係中的反轉和級聯

1、反轉:

反轉操作在對映檔案中通過對集合的inverse屬性設定,來控制關聯關係和物件的級聯關係。
inverse預設為false,關係的兩端都能夠控制,但會造成更新時出現重複更新的情況,產生多餘的SQL語句。所以在實際開發中,一對多的時候,將一的一方inverse設定為true,即由多的一方維護關聯關係;多對多則任意設定一方即可。(ps:inverse只對<set>、<one-to-many>、<many-to-many>有效)。

2、級聯:

當主控方執行儲存、更新、或刪除操作時,關聯物件也執行相同操作。通過對cascade屬性的設定來控制是否使用級聯。
cascade屬性值:
- save-update:在執行save、update、或saveOrUpdate時進行關聯。
- delete:在執行delete操作時進行關聯
- delete-orphan:表示孤兒刪除,刪除所有和當前物件解除關聯的物件
- all:所有情況下都進行關聯,但不包括delete-orphan
- all-delete-orphan:所有情況下都進行關聯
- none:所有情況下都不進行關聯。這個是預設的

一對多級聯儲存:
儲存一的同時,儲存一旗下的多。

/**
	 * 一對多級聯儲存
	 */
	@Test
	public void testCascade1() {
		//獲得session物件
		Session session = getSession();
		//通過session開啟事務
		Transaction trans = session.beginTransaction();
		
		//建立一個客戶物件
		Customer customer = new Customer();
		customer.setName("馬化騰");
		//建立兩個訂單
		Order order1 = new Order(1000,"矽谷");
		Order order2 = new Order(2000, "大學城");
		//客戶關聯訂單
		customer.getOrderSet().add(order1);
		customer.getOrderSet().add(order2);
		//僅儲存客戶
		session.save(customer);
		
		//提交事務
		trans.commit();
		session.close();
	}
 
         (在僅儲存的那一方的xml檔案中加上,cascade)
       <set name="orderSet" table="orders" cascade="save-update">
        	<!-- 外來鍵 -->
            <key>
                <column name="customer_id"/>
            </key>
            <one-to-many class="wan.bean.Order" />
        </set>

一對多級聯刪除:
刪除一的同時,刪除一旗下的多。如果不配置xml,則只刪除一,然後將一旗下的多的外來鍵置null。

/**
	 * 一對多級聯刪除(如果不在xml中配置cascade="delete",則只能刪除customer,然後將order的外來鍵置null)
	 */
	@Test
	public void testCascade2() {
		//獲得session物件
		Session session = getSession();
		//通過session開啟事務
		Transaction trans = session.beginTransaction();
		
		//得到一個客戶物件
		Customer customer = session.get(Customer.class,40023);
		//刪除客戶
		session.delete(customer);
		
		//提交事務
		trans.commit();
		session.close();
	}
 
 <set name="orderSet" table="orders" cascade="delete">
        	<!-- 外來鍵 -->
            <key>
                <column name="customer_id"/>
            </key>
            <one-to-many class="wan.bean.Order" />
        </set>

一對多孤兒刪除:
刪除多,且只刪除外來鍵為null的多。

/**
	 * 孤兒刪除:刪除多,且只刪除外來鍵為null的多
	 */
	@Test
	public void testCascade3() {
		//獲得session物件
		Session session = getSession();
		//通過session開啟事務
		Transaction trans = session.beginTransaction();
		
		//得到一個客戶物件
		Customer customer = session.get(Customer.class,40022);
		//得到客戶旗下的訂單
		Order order1 = session.get(Order.class,29);
		Order order2 = session.get(Order.class,30);
		//解除關係
		customer.getOrderSet().remove(order1);
		customer.getOrderSet().remove(order2);
		//提交事務
		trans.commit();
		session.close();
	}
 
 <set name="orderSet" table="orders" cascade="delete-orphan">
        	<!-- 外來鍵 -->
            <key>
                <column name="customer_id"/>
            </key>
            <one-to-many class="wan.bean.Order" />
        </set>

多對多級聯儲存:

/**
	 * 級聯新增(只在teacher.hbm.xml中新增級聯屬性為save-update)
	 */
	@Test
	public void testAdd3() {
		//獲得session物件
		Session session = getSession();
		//通過session開啟事務
		Transaction trans = session.beginTransaction();
		
		//建立兩個老師,兩個班級
		Teacher t1 = new Teacher("馬雲");
		Teacher t2 = new Teacher("馬化騰");
		Classes c1 = new Classes("通訊141");
		Classes c2 = new Classes("通訊142");
				
		//建立聯絡
		t1.getClassesSet().add(c1);
		t1.getClassesSet().add(c2);
		t2.getClassesSet().add(c1);
		t2.getClassesSet().add(c2);
  
		session.save(t1);
		session.save(t2);
		trans.commit();
		session.close();
	}
 
  <set name="classesSet" table="classes_teacher" cascade="save-update">
            <key>
                <column name="t_id" />
            </key>
            <!-- 多對多對應Classes POJO類,該類對應中間表的c_id -->
            <many-to-many class="Classes" column="c_id"/>
        </set>

或者:

/**
	 * 級聯新增(只在兩張hbm.xml中都新增級聯屬性為save-update)
	 */
	@Test
	public void testAdd4() {
		//獲得session物件
		Session session = getSession();
		//通過session開啟事務
		Transaction trans = session.beginTransaction();
		
		//建立兩個老師,兩個班級
		Teacher t1 = new Teacher("劉強東");
		Teacher t2 = new Teacher("雷軍");
		Classes c1 = new Classes("通訊141");
		Classes c2 = new Classes("通訊142");
				
		//建立聯絡
		t1.getClassesSet().add(c1);
		t1.getClassesSet().add(c2);
		t2.getClassesSet().add(c1);
		t2.getClassesSet().add(c2);
		c1.getTeacherSet().add(t1);
		c1.getTeacherSet().add(t2);
		c2.getTeacherSet().add(t1);
		c2.getTeacherSet().add(t2);
  
		session.save(t1);
		trans.commit();
		session.close();
	}

多對多級聯刪除:

/**
	 * 刪除(無級聯配置,刪除該Teacher物件和中間表)
	 */
	@Test
	public void testDel2() {
		//獲得session物件
		Session session = getSession();
		//通過session開啟事務
		Transaction trans = session.beginTransaction();
		
		Teacher teacher = session.get(Teacher.class, 31);
		session.delete(teacher);
		trans.commit();
		session.close();
	}
 
 
 /**
     * 級聯刪除(在兩個hbm.xml中加入級聯刪除,且在Classes.hbm.xml中加入inverse="true")
     * 將會刪除和該Teacher有關的一切
	  */
	@Test
	public void testDel1() {
		//獲得session物件
		Session session = getSession();
		//通過session開啟事務
		Transaction trans = session.beginTransaction();
		
		Teacher teacher = (Teacher) session.get(Teacher.class, 30);
		session.delete(teacher);
		trans.commit();
		session.close();
	}