在上一篇Hibernate總結(一)簡單總結了一級緩存,快照,增刪改查的簡單使用,這一篇總結兩張表的級聯操作。
級聯涉及到三種情況,many-many,1-many,many-1。
//因為太占版面緣故,沒有列出get()/set()方法
public class Customer {
private Integer id;
private String name;
private Set<Order> orders = new HashSet<Order>();//1對多
}
public class Order {
private Integer id;
private String name;
private Customer customer;//多對1
}
接下來是hibernate.cfg.xml與兩個實體類的配置文件Order.hbm.xml與Customer.hbm.xml,第一個不多說,主要是映射文件的配置
//Customer.hbm.xml
<hibernate-mapping package="king.domain">
<class name="Customer" table="t_customer">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" column="name"></property>
<!-- 一對多關系 -->
<!--
inverse:true 不維護關系,交給擁有外鍵一方維護
cascade:save-update(級聯保存與級聯更新),當然還有其它選項,delete(級聯刪除),all(級聯保存,更新,刪除),none(默認沒有級聯)
-->
<set name="orders" inverse="true" cascade="save-update">
<key column="cid"></key> <!-- 在Order表中的外鍵的名字-->
<one-to-many class="Order"/>
</set>
</class>
</hibernate-mapping>
//Order.hbm.xml
<hibernate-mapping package="king.domain">
<class name="Order" table="t_order">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" column="name"></property>
<!-- 多對一關系 -->
<!-- 含有外鍵一方維護關系 -->
<many-to-one name="customer" column="cid" class="Customer"></many-to-one>
</class>
</hibernate-mapping>
一切准備就緒,開始級聯的代碼:
因為代碼中大量使用了得到連接,關閉連接操作,所以我使用了模板設計模式,在我的文章《Hibernate-模板模式》有講解
/**
* 級聯保存:
* 1.inverse="true",維護關系,最好只有一方維護,而且是擁有外鍵一方維護
* 2.cascade="save-update",級聯保存與級聯更新
*/
@Test
public void test0() {
new SessionTemplate(){
@Override
public void fun(Session s) {
Customer c=new Customer();
c.setName("King");
Order o1=new Order();
o1.setName("炒面");
Order o2=new Order();
o2.setName("肉");
o1.setCustomer(c);//由擁有外鍵一方維護關系
o2.setCustomer(c);
s.save(c);
s.save(o1);
s.save(o2);//這樣框架只執行了3條SQL語句
}
}.execute();
}
/**
* 級聯刪除:
* 1.inverse="false"為默認處理方式:把客戶的訂單的外鍵修改為null,然後再刪除客戶
* 2.inverse="true"若客戶不處理,會出錯
*/
@Test
public void test1() {
new SessionTemplate(){
@Override
public void fun(Session s) {
//這是沒有使用級聯刪除的情況,這時cascade為save-update
Customer c=(Customer) s.get(Customer.class, 3);
for(Order o:c.getOrders()){
s.delete(o);
}
s.delete(c);//此時,inverse="true",所以前面刪除了所有客戶的訂單才能刪除客戶
//更改配置文件,cascade為delete,這時就是級聯刪除
Customer c=(Customer) s.get(Customer.class, 3);
s.delete(c);//這時不需要手動刪除訂單了
}
}.execute();
}
/**
* 級聯更新
* cascade為save-update
*/
@Test
public void test2() {
new SessionTemplate(){
@Override
public void fun(Session s) {
Customer c=(Customer) s.get(Customer.class, 2);
for(Order o:c.getOrders()){
o.setName("羊雜湯");//持久態,不需要更新
}
}
}.execute();
}
查詢涉及到了加載策略,所以很復雜,所以將在寫在下一篇中。
public class Student {
private Integer id;
private String name;
private Set<Course> courses=new HashSet<>();//多對多
}
public class Course {
private Integer id;
private String name;
private Set<Student> students=new HashSet<>();//多對多
}
接下來是兩個實體類與數據庫表的映射文件:
//Student.hbm.xml
<hibernate-mapping package="king.domain">
<class name="Student" table="t_student">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" column="name"></property>
<!-- 多對多關系,在多對多中,需要雙方都設置存儲關系的表名 -->
<set name="courses" cascade="save-update" table="t_selectcourse">
<key column="sid"></key>
<many-to-many class="Course" column="cid"></many-to-many>
</set>
</class>
</hibernate-mapping>
//Course.hbm.xml
<hibernate-mapping package="king.domain">
<class name="Course" table="t_course">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" column="name"></property>
<!-- 多對多關系 -->
<!-- 維護權反轉給對方 -->
<set name="students" inverse="true" table="t_selectcourse">
<key column="cid"></key>
<many-to-many class="Student" column="sid"></many-to-many>
</set>
</class>
</hibernate-mapping>
一切准備繼續,開始代碼工作:
/**
* 多對多
* 級聯保存:
* 本來想也寫上級聯刪除與級聯更新,但是發現寫的代碼和我想要實現的結果不同,故沒有貼出代碼,額...我的意思就是我也不會...挺尴尬...
*/
@Test
public void test0() {
new SessionTemplate(){
@Override
public void fun(Session s) {
Student s1=new Student();
s1.setName("King");
Course c1=new Course();
c1.setName("數學");
Course c2=new Course();
c2.setName("英語");
s1.getCourses().add(c1);//由學生維護關系
s1.getCourses().add(c2);//由學生維護關系
s.save(s1);
}
}.execute();
}
增刪改查,現在就差“查”沒有寫出,我將在下一篇總結中寫出Hibernate的關於查詢的加載策略。