|
在Java程式中,物件與物件之間會透過某些關係互相參考,如果有一個物件已經是持久化物件,被它參考的物件直覺上也應該要持久化,以維持物件之間關聯的
完整性,這是藉由可達性完成持久化(Persistence by reachability)的基本概念。 如果將物件之間的關聯想像為一個樹狀圖,從某一個持久化物件為樹根出發,父節點若是持久化物件,則被父節點參考到的子節點應自動持久化,而另一方面,如果 有一子節點沒辦法藉由任何的父節點來參考至它,則它沒有被持久化的需求,它應從資料庫中加以刪除。 完整的掃描物件圖中的所有物件是否該持久化,牽涉到記憶體與資料庫中所有相關表格的掃描,在效能上無法接受這樣的概念,所以Hibernate並沒有完全 實現以上的概念,它讓使用者自行決定自動持久化的方式,當物件之間被指定關聯(例如多對一、一對多等),您可以決定被持久化 物件關聯的暫存對象是否進行自動持久化與如何自動持久化。 在Hibernate中是以映射文件中標籤上的cascade屬性來設定,預設上是none,以 多對一 中的範例來說,如果不設定cascade為true,則您必須分別對User實例與Room實例進行儲存: Room room1 = new Room();
room1.setAddress("NTU-M8-419"); Room room2 = new Room(); room2.setAddress("NTU-G3-302"); User user1 = new User(); user1.setName("bush"); user1.setRoom(room1); User user2 = new User(); user2.setName("caterpillar"); user2.setRoom(room1); User user3 = new User(); user3.setName("momor"); user3.setRoom(room2); Session session = HibernateUtil.getSessionFactory().openSession(); Transaction tx = session.beginTransaction(); // 儲存Room實例 session.save(room1); session.save(room2); // 儲存User實例 session.save(user1); session.save(user2); session.save(user3); tx.commit(); session.close(); cascade屬性需要設置多個值時,可以使用逗號區隔,例如: <many-to-one name="room" column="room_id" class="onlyfun.caterpillar.Room" cascade="save-update, pesist, merge" outer-join="true"/> 使用cascade自動持久化時,會先檢查被關聯物件的id屬性,未被持久化的物件是否儲存是藉由id屬性的unsaved-value決定,預設是 null,也就是沒有參考至任何值時儲存物件,如果您使用int、long這樣的原生型態(Primitive type)時,由於資料成員的初始會被設定為0,所以您必須自行指定預設值,例如(如果id的資料型態是long的話): .... <id name="id" column="id" unsaved-value="0"> <generator class="native"/> </id> .... |