Hibernate(5.3.7)關聯關係中的反轉和級聯
阿新 • • 發佈:2018-12-09
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();
}