2017-03-08 39 views
0

我喜歡hibernate,我有一個關於錯誤處理和持久性工作流的問題。我有以下一段遺留代碼。Hibernate持久化和錯誤處理工作流程

public void doPersist(Contact out){ 
    contactValidator.validationOne(out); 
    entityManager.persist(out); 
    contactValidator.validationTwo(out); 
    contactValidator.validationThree(out); 
} 

ContactValidator是用於驗證的聯繫人一類,它拋出在每個驗證方法的多業務異常。我不喜歡doPersist的構建方法。爲什麼它首先調用entityManager.persist然後驗證對象?如果某些驗證方法出現異常,則應該回滾數據。當persist已被調用時,Hibernate將如何回滾數據?

回答

1

我個人不在乎如何編寫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-validatorhibernate-core,您將自動獲得Bean驗證爲免費,因爲Hibernate會插入驗證框架和執行驗證操作爲以下事件

  • PrePersistEvent
  • PreUpdateEvent
  • PreRemoveEvent

正如你所看到的,沒有任何開箱即用事件支持。這很有意義,因爲在實際保存或更新數據庫行之前,通常需要滿足約束條件。這就是爲什麼我發現你的第二個和第三個接觸驗證方法很奇怪。除此之外,如果您真的需要一些後插入或更新後驗證,您可以使用在PostInsertEventPostUpdateEvent組上註冊的自定義Hibernate偵聽器輕鬆綁定到現有Bean驗證程序偵聽器中以執行這些操作調用bean驗證。

+0

謝謝。這是非常豐富的。我是一名pl/sql開發人員,在我以前的經驗中,我總是將事務(開始,提交,回滾)管理到存儲過程框架中。現在使用hibernate + db2,我不太清楚如何管理事務。實際的問題是驗證三種會導致死鎖,但我認爲你的解釋有助於我解決它。 –

+0

想象一下,你在'begin()'和'commit()'之間執行的所有java代碼都是PL/SQL過程。在該過程中,您通常也會使用try/catch塊,以便您可以以不同的方式處理特定的錯誤條件。 Java真的沒有什麼不同。當您使用Spring和JavaEE等框架時,可以使用註釋來抽象事務管理,因此如果您處於這種類型的環境中,請務必理解這些工作是如何工作的。 – Naros