iT邦幫忙

2024 iThome 鐵人賽

DAY 15
0
Software Development

週日時在做什麼?有沒有空?可以來寫SpringBoot嗎?系列 第 15

[DAY 15] 講到爛但還是很重要的ACID與隔離層級(後)

  • 分享至 

  • xImage
  •  

上次我們提到了資料庫的四大特性,以及為了關聯式資料庫的隔離層級。這次我想針對Hibernate的一些特性再做一些補充。

Hibernate是Spring 的ORM框架,Hibernate負責管理與資料庫間的溝通,當中物件可以被分為四種狀態:

  1. Transient
    這是在物件被建立後,被儲存進資料庫之前的狀態。
  2. Persistent
    這是物件與資料庫有對應關係,並且在Session的連線狀態中。物件呼叫Session的save()方法後,就會到Persistent狀態。
  3. Detached
    與資料庫有id對應的物件在Session關閉後,就會到這個狀態。
  4. Removed
    如果使用Session的remove()方法刪除資料,就會到這個狀態。

在這四種狀態中,比較重要的狀態就是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集完結篇吧,超好看的喔


上一篇
[DAY 14] 講到爛但還是很重要的ACID與隔離層級(前)
系列文
週日時在做什麼?有沒有空?可以來寫SpringBoot嗎?15
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言