標籤:程式 參考 不一致 多個 ber 屬性 預設 rate 資料
配置關聯時,我們考慮兩點:程式執行效率和實際業務需要,前面的例子中無論是單向的關聯還是雙向的關聯,我們都要分別對實體類使用session.save()才能將資料儲存至資料庫。
問題:如果儲存資料非常多,那編碼是一件恐怖的事情。
有沒有簡單的方法呢?
將<set>標籤cascade=all
總結:我們只對district對象執行了持久化操作,但是通過sql語句,我們發現street執行了持久啊操作,這就是cascade屬性的作用。當設定cascade屬性不none時,Hibernate會持久化所關聯的對象。
1.all :對象所有操作進行級聯操作 save,update,delete
2.save-update : 執行儲存和更改操作時進行級聯操作
3.delete : 執行刪除操作時進行級聯操作
4.none : 對所有操作不進行級聯操作 預設
cascade屬性的設定往往會帶來效能上的變動,請謹慎設定。
例如:對district對象進行儲存或更改操作時,district對象不一定有關聯的street對象,或street對象不一定也需要更新,但是刪除district對象時同時刪除它所關聯的street對象
因此:將cascade屬性設定為all是不恰當的,應該設定為delete
Hibernate: insert into district (name, id) values (?, ?)
Hibernate: insert into street (name, district_id, id) values (?, ?, ?)
Hibernate: update street set district_id=? where id=?
1.第一條語句:比較好理解,插入新的區資料
2.第二天語句:這裡為什麼出現insert街道呢?我們並沒有編寫session.save(street)?
答案:其實我們在district端設定了串聯更新(cascade=”all”)
也即是說,當HIbernate在向district插入”新“對象記錄時,會檢查“district”對象所關聯的屬性(就是<set>對應的屬性)是否發生變化,如果發生變化就按設定的內容進行操作。因為調用了district.getStreet().add(street),所有Hibenate插入district時候,也一同把它所關聯的瞬時狀態的對象一同插入到對應的表中區。
Hibernate: update street set district_id=? where id=?
3.第三條語句:是update語句,為什麼重複更新記錄?
答:Hibernate將district與street之間的關聯交由district來維持,就district而言,它要先儲存自己,然後儲存它所包括的多個street,之後對每一個street更新(update)對自己(district)的關聯。
就district而言,它並不知道它所包括的street是不是已儲存的對象,或者即使是已儲存物件,也不知道street表格上的district_id是不是參考至district表格的id
所以,它必須針對自己所有包括的street對象進行更新,以確保street表格上的district_id是指向自己的。
正因為如此,所以Hibernate“怕”在進行”district.getStreet().add(street)”這樣操作時,出現意外情況(如street.getClss=null,street沒有所屬的區)
存在外鍵不一致的情況。所有出現了這條多餘的update語句。
也就是由one-to-many中一的一方(district端)主動維護外鍵,以保證所有包含district對象的集合裡的所有street對象都要與自己(district)有外部索引鍵關聯。
通俗講:每年開學新生報到,班級老師主動邀請同學,而不是同學自己來報到。可想而知效率怎麼樣?
Hiberate有沒有提供解決這種情況的辦法呢?
當然有:那就是設定inverse屬性!!
hibernate中 cascade屬性詳解