我目前正在重構已使用JPA的應用程序,但JPA EnitytManager
(和事務)當前的作用域爲DAO層。還有一個存儲庫層和一個服務層。我想使服務層成爲事務性的,並且在服務層上每個請求有一個EntityManger
。理想情況下,我不希望我的服務或存儲庫層知道關於JPA的任何信息。JPA模型驗證和事務處理
當前存儲庫和服務層使用從DAO層獲得的分離實體。對模型進行更改並將實體合併回DAO層。在新結構中,實體在整個請求期間保持被管理,並且1個請求包含在1個事務中。變更在交易結束時自動提交。這看起來更像JPA的精神,並且在最常見的情況下工作得很好。
雖然有時會對模型進行更改,然後對模型進行驗證。如果模型無效,則不應保存更改。在舊的結構中,這很簡單:
在這個例子中,過程基本上是一個圖,整個圖必須驗證,沒有自引用,每個節點都必須可達,第一個節點有一些特殊需求,成爲最終節點等等。我們首先對模型進行修改,然後驗證模型。
庫層的代碼的時候:
changeProcessModel();
messages = ProcessValidator.validate(process);
if (messages.hasNoErrors()) {
processDao.merge(process);
messages.addInfoMessage("Process was updated succesfully");
}
return messages;
在新的結構,我想我有三種選擇,我哪一個被認爲是最好的做法質疑,或是否有任何其他的替代品。
新的代碼選項1:
changeProcessModel();
messages = ProcessValidator.validate(process);
if (messages.hasNoErrors()) {
messages.addInfoMessage("Process was updated succesfully");
} else {
throw new InvalidProcessException(messages);
}
return messages;
此代碼濫用的排序爲一些業務規則驗證一個RuntimeException
。我不認爲這被認爲是最佳做法,但交易是回滾的。這也與Bean Validation實例兼容,如果實體不驗證,它也會引發異常。
新的代碼選項2:
changeProcessModel();
messages = ProcessValidator.validate(process);
if (messages.hasNoErrors()) {
messages.addInfoMessage("Process was updated succesfully");
} else {
em.getTransactionManager.rollback();
}
return messages;
此代碼直接做在JPA TransactionManager
回滾,並介紹了我的倉庫層和JPA之間的相關性。
新的代碼選項3:
changeProcessModel();
messages = ProcessValidator.validate(process);
if (messages.hasNoErrors()) {
messages.addInfoMessage("Process was updated succesfully");
} else {
processDao.refresh(process);
}
return messages;
這段代碼看起來很不錯,但它不依賴於CascadeType.REFRESH
就需要刷新的過程中實體間關係正確設置。
我也可以例如到processDao.clear();
或processDao.rollback();
但是這增加了processDao
的範圍到整個entityManger
。我不確定這是否是一種非常乾淨的方法。
你對此有何看法?