在上一篇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的關於查詢的加載策略。