4.1 交易和數據庫完整性
數據庫的正常運行模式是每分鐘從數百個不同的客戶端接收數千個請求。在這種情況下,經常會出現從不同查詢訪問相同數據的情況。
不太常見,但有時會出現一個請求讀取某一行,而另一個請求同時更改它的情況。想像一下,如果有人讀到一行只改變了一半會怎樣?沒什麼好的。
這個問題可以通過幾種方式解決。首先,您可以只鎖定更改的行。既適合閱讀,也適合寫作。這種方法有效,但基地的速度受到很大影響。
第二種方法是將字符串鎖定為只寫。但是,當有人試圖閱讀部分修改的行時,仍然會出現問題。結論 - 不應該出現線路被部分更改的情況。
因此,他們想出了第三種方法——交易。事務是一組操作,這些操作要么一起執行,要么根本不執行。不能出現部分動作執行了而第二部分沒有執行的情況。如果不可能進行所有更改,則回滾所有已進行的更改。
任何現代 SQL 服務器都允許您僅在事務中更改數據。您打開一個事務,對任意數量的表進行任何更改,然後提交該事務。SQL Server 然後嘗試進行更改。如果一切正常,那麼它們將被添加到通用數據庫中。如果出現問題,則所有更改都將被取消。
Hibernate 也使用這種範式。這就是為什麼在上一講中我們看到,當試圖將 Employee 對象保存到數據庫時,首先打開一個事務,保存之後,它被提交。
我們將更詳細地探討這個主題,但現在,只知道為什麼需要事務以及它們通常用在什麼地方。
4.2 獲取對象
如果 Hibernate 執行獲取數據的請求,則無需顯式開啟事務。如果 Hibernate 認為合適,它自己會這樣做:它有自己的設置,以及 SQL 服務器的設置。
我們將分析如何使用數據庫。其中最簡單的是通過ID獲取對象。為此,請使用會話get()
對像上的方法。這種請求的一般形式:
Class Name = session.get(Class.class, ID);
例子:
public User getUserById(Integer id) {
try (Session session = sessionFactory.openSession()) {
User user = session.get(User.class, id);
return user;
}
}
4.3 保存(添加)對象
如果你想將你的對象保存到數據庫中,那麼查詢將在 SQL 級別執行插入. 因此,您的操作必須作為單獨的交易執行。另外,最好使用會話persist()
對象的持久化方法。
這種請求的一般形式:
session.persist(An object);
該方法persist()
不僅改變了基礎,而且改變了對象本身。問題是,當我們向數據庫中添加一個對象時,這個對像在添加之前還沒有自己的ID。好吧,通常是這樣,儘管有細微差別。添加對像後已經有一個 ID 。
public boolean saveUser(User user) {
try (Session session = sessionFactory.openSession()) {
Transaction transaction = session.beginTransaction();
session.persist(user);
transaction.commit();
return true;
}
catch() {
return false;
}
}
Session對像也有一個save()
執行類似功能的方法。只是方法save()
是舊的Hibernate標準,方法persist()
是JPA標準。
4.4 刪除對象
如果要刪除現有對象,那麼這樣做非常容易。為此,會話對像有一個特殊的方法 - remove()
。
這種請求的一般形式:
session.remove(An object);
當然,讓我們用一個例子來編寫代碼:
public boolean removeUser(User user) {
try (Session session = sessionFactory.openSession()) {
Transaction transaction = session.beginTransaction();
session.remove(user);
transaction.commit();
return true;
}
catch() {
return false;
}
}
你問為什麼這麼難?
好吧,首先,對數據庫的任何更改總是會產生不同且並不總是顯而易見的後果。其次,這個對象可能有與之關聯的子對象,等等。所以刪除場景通常很重要。
GO TO FULL VERSION