國家名單

現在樂趣開始了。我們將研究實體對象的狀態。你必須為所有東西付費,使用 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