我個人不在乎如何編寫doPersist
方法,因爲我可以看到幾個更清潔的替代方案,避免使用這種多餘的方法。
要回答您的具體問題,回滾的魔力發生是因爲事務如何工作。交易只不過是一系列以單一工作單位執行的操作,必須堅持原子性,一致性,隔離性和持久性(例如ACID)。
雖然事務處於活動狀態並且尚未提交,但如果引發異常,則異常處理會告知事務處理,以便忘記所要執行的操作。
Session session = sessionFactory.openSession();
try {
session.getTransaction().begin();
// do whatever work you want to do here
session.getTransaction().commit();
}
catch (Throwable t) {
if (session.getTransaction().isActive()) {
session.getTransaction().rollback();
}
throw t;
}
finally {
session.close();
}
所以在這個代碼,即使該事務試圖提交併拋出一個異常,catch子句看到它是積極和滾動交易回,從而告訴數據庫扔掉所有的工作它只是被要求執行。
現在我想談談你的ContactValidator。
我的猜測是你的ContactValidator
與Bean驗證如何緊密結合。它基本上看着bean的狀態,並確保沒有任何不一致的期望,如果是這樣,斷言與一個例外。
當結合使用hibernate-validator
與hibernate-core
,您將自動獲得Bean驗證爲免費,因爲Hibernate會插入驗證框架和執行驗證操作爲以下事件
- PrePersistEvent
- PreUpdateEvent
- PreRemoveEvent
正如你所看到的,沒有任何開箱即用事件支持。這很有意義,因爲在實際保存或更新數據庫行之前,通常需要滿足約束條件。這就是爲什麼我發現你的第二個和第三個接觸驗證方法很奇怪。除此之外,如果您真的需要一些後插入或更新後驗證,您可以使用在PostInsertEvent
和PostUpdateEvent
組上註冊的自定義Hibernate偵聽器輕鬆綁定到現有Bean驗證程序偵聽器中以執行這些操作調用bean驗證。
謝謝。這是非常豐富的。我是一名pl/sql開發人員,在我以前的經驗中,我總是將事務(開始,提交,回滾)管理到存儲過程框架中。現在使用hibernate + db2,我不太清楚如何管理事務。實際的問題是驗證三種會導致死鎖,但我認爲你的解釋有助於我解決它。 –
想象一下,你在'begin()'和'commit()'之間執行的所有java代碼都是PL/SQL過程。在該過程中,您通常也會使用try/catch塊,以便您可以以不同的方式處理特定的錯誤條件。 Java真的沒有什麼不同。當您使用Spring和JavaEE等框架時,可以使用註釋來抽象事務管理,因此如果您處於這種類型的環境中,請務必理解這些工作是如何工作的。 – Naros