上次我們提到了資料庫的四大特性,以及為了關聯式資料庫的隔離層級。這次我想針對Hibernate的一些特性再做一些補充。
Hibernate是Spring 的ORM框架,Hibernate負責管理與資料庫間的溝通,當中物件可以被分為四種狀態:
在這四種狀態中,比較重要的狀態就是Persisent狀態,因為只有這個狀態受到Session的掌控,那假設物件的屬性在交易中發生變化,但整個交易還沒有結束的這個階段,這部分的資料被稱作髒資料(Dirty Data),對應至上一輪提到的髒讀(Dirty Read)。
之後,在交易結束時,Hibernate會一併觸發commit()方法,這時,Hibernate會在資料提交時找出與要儲存的物件對應的資料庫物件,並執行更新。
而Java識別物件的方法主要有兩種方式,一種是根據記憶體位置來決定的,以程式來說的話就是==,另外一種就是利用.equals()與.hashCode()判斷。
在Hibernate中,在同一個Session中根據相同的查詢得到的相同的資料,會共享同一個記憶體位址。但如果是在不同的Session中使用相同的查詢,則會擁有不同的位址。
因此,如果想要比對兩個物件是否相等,用==是不可行的。正確的應該是覆蓋.equals()與hashCode()方法去撰寫判斷。
常見的物件相等性的比對方法是使用id判斷,但這會有一個問題,如果是尚未儲存的物件,因為id 有些是 auto_increment,也就是說只有進到資料庫中才會被賦予一個id,那這個方法就會不適用。因此要判斷物件相等性的方法還是要回到資料本身,資料本身獨一無二的值去判斷才能確保得到的回覆是正確的。
簡單來說,假設是兩筆Order物件要比較是不是同樣一筆訂單,在利用Hibernate特性的id比較前,你應該重新回到商業邏輯的考量,也就是說應該真正該被利用的是訂單編號。 ( 除非你的系統想設計成重複訂單編號可以存在,但個案不討論。)
那麼今天的分享就到這邊了,在寫這次文章前,equals()與hashCode()我只對他們有著模糊的理解,但後面隨著漸漸了解才發現被使用到的地方這麼多,希望這些文章能為他人帶來一點新知識。那麼今天的文章雖然有點短,不過我想就在這裡結束吧,感謝各位。
請去看敗北女主12集完結篇吧,超好看的喔