國家名單
現在樂趣開始了。我們將研究實體對象的狀態。你必須為所有東西付費,使用 Hibernate 也是如此。你不覺得學習HQL是要付出這樣的代價嗎?不,生活有點複雜。
如果你有某種可以使用 Hibernate 保存到數據庫中的 Entity 對象,那麼從 Hibernate 的角度來看,這個對象可以有四種狀態:
- 短暫的
- 持久(或託管)
- 分離的
- 刪除
為了讓您感興趣,我將在本次講座中添加這張照片:

短暫的
事實上,一切都比看起來簡單得多,儘管並非沒有細微差別。例如,您使用 Java 代碼顯式創建且未使用 Hibernate 從數據庫加載的每個實體對像都具有 Transient(透明)狀態。
EmployeeEntity employee = new EmployeeEntity();
Transient 狀態表示 Hibernate 對這個對像一無所知,對該對象的任何操作都不會影響 Hibernate,Hibernate 對這個對象的工作也不受影響。
此類對像也稱為POJO - Plain Old Java Object。該術語通常用作具有棘手行為的各種對象的反義詞。還記得 Mockito 創建的 Moc 對象嗎?在這裡他們不是 POJO。
如果某些客戶端代碼與具有 Transient 狀態的對像一起工作,那麼它們的交互可以用一個超級簡單的方案來描述:

持久或託管
下一個最常見的情況是與 Hibernate 引擎相關的對象。它們的狀態稱為持久性(或託管)。有兩種方法可以獲取具有此狀態的對象:
- 從 Hibernate 加載對象。
- 在 Hibernate 中保存對象。
例子:
Employee employee = session.load(Employee.class, 1);
Employee employee = new Employee ();
session.save(employee);
這樣的對象通常對應數據庫中的某種記錄,它有一個ID之類的。該對象附加到 Hibernate 會話,通常不能由真實對象表示,而是由某種代理表示。
很可能在調用session.load()方法之後,你會得到一些存根對象(代理),所有對數據庫的調用都會在調用這個對象的方法之後執行。但是我們稍後會討論這些細節。
而客戶端代碼與Managed狀態對象的交互可以用下圖來描述:

分離的
下一個狀態是對像從會話中分離出來的時候。也就是說,一旦對像被附加到 Hibernate 會話中,但是隨後會話被關閉或者事務結束,Hibernate 就不再監視這個對象。
例子:
session.close();
session.evict(entity);
在第一個示例中,會話已關閉。在第二種情況下,我們明確指出我們希望使用evict()方法將對像從會話中分離出來。
新的代碼對象交互方案將如下所示:

這就是它變得有趣的地方。如果你的對像是從 Hibernate 獲得的,那麼你很可能得到了一個代理而不是一個真實的對象。而這個代理對象,在與會話斷開連接後,調用它的方法時會拋出異常。
這是所有初學者在使用 Hibernate 時最常見的問題。當您使用 Entity 對象時,您需要在任何給定時間準確地知道此類問題的答案:
- 你有一個真實的對像還是只是一個真實對象的代理?
- 您目前是否在交易中?
- 是讀寫事務還是只讀事務?
- 對像是否被LazyLoading機制管理?
- 對象的哪些部分已經加載到內存中,訪問時將加載哪些部分?
- 您的對像如何連接到依賴對象?
好消息是大多數時候它是顯而易見的。但是您仍然需要了解它在幕後是如何工作的。聲明式編程就是這樣 - 您可以在 10 分鐘內編寫代碼,理解為什麼它不能正常工作 - 在 10 小時內:)
刪除
Entity 對象的最後一個狀態是 Removed。正如您可能已經從其名稱中猜到的那樣,這是遠程對象的狀態。
出現這種狀態是因為如果您從數據庫中刪除某個對象,那麼 Java 對像不會立即消失在任何地方。
Employee employee = session.load(Employee.class, 1);
//after loading the object's state is Persisted
session.remove(employee);
//after deletion, the state of the object is Removed
session.save(employee);
//and now Persisted again
session.close();
//and now the Detached state
GO TO FULL VERSION