說我有以下部署爲本地SLSB通用的DAO:應該在EJB 3.0 DAO中使用em.flush來抽象持久層?
public interface CrudService {
public <T> T create(T t);
public <T> T find(Object id, Class<T> type);
public <T> T update(T t);
public void delete(Object t);
public List<Object> findByNamedQuery(String queryName);
public List<Object> findByNamedQuery(String queryName, int resultLimit);
public List<Object> findByNamedQuery(String namedQueryName, Map<String, Object> parameters);
public List<Object> findByNamedQuery(String namedQueryName, Map<String, Object> parameters, int resultLimit);
}
這DAO是從許多其他SLSB服務使用。我想從業務邏輯中抽象出整個持久層(所有操作和異常)。我創建了@AroundInvoke方法攔截像下面,把它放在DAO的類層次:
@AroundInvoke
public Object wrapExceptions(InvocationContext context) throws Exception {
try {
return context.proceed();
} catch(Exception e) {
throw mapToApplicationException(e)
}
}
沒有異常被捕獲,並因此映射具有DAO方法的默認實現。 但是如果我在持久化結束時使用flush,更新和刪除它的工作方式 - 那沒關係。
現在我的問題是:它是唯一能讓它工作的方法嗎?我知道調用flush是相當沉重的,如果我需要打電話讓我們說更新多次,這將是一個嚴重的瓶頸。
編輯: 另一種選擇是使用BMT,但它會導致與tx.begin()等被污染的所有門面方法......克里斯·巴比奇答案後
編輯:
我根據克里斯的提議有些疑問。處理服務層中的PersisteceExceptions會導致混合圖層透明度。但這對我來說並不是最糟糕的。假設我有服務門面使用我的服務或DAO集。服務門面方法需要在自己的事務上執行,所以我會使用CMT並用@TransactionAttribute(REQUIRES_NEW)標記它。這樣做沒有地方可以有異常處理點(攔截器不起作用,因爲交易仍在進行中 - 這與上述情況相同)。所以我看到兩種方法:要麼有所有的外觀方法使用BMT並處理所有的tx.begin(),tx.commit()等東西,要麼有另一個「Facade for Facade」擁有@TransactionAttribute(從不),然後調用交易門面和處理它是例外。
記住生命週期攔截器不需要在服務本身中定義。您希望將常見攔截邏輯(如錯誤處理)分離爲可應用於多個類,服務等的獨立攔截器類。此分隔可讓您將業務功能與標準異常之間的關注區分開來處理。 – 2011-03-24 22:08:59
至於持久性異常與其他異常之間的區別,取決於異常處理的目標。你在乎什麼是例外情況或者發生了錯誤情況?您是試圖實現一個通用的錯誤處理框架,還是需要以不同的方式處理每種類型的錯誤?通過異常處理,您應該實現一個通用處理框架,並且只能手動處理需要處理的異常或需要應用程序更改其處理流程的異常。其餘的應該由你的錯誤框架自動處理。 – 2011-03-24 22:11:24
也許我沒有說清楚。我的前夫。處理攔截器實際上是一個獨立的類。根據異常處理,我希望我的服務門面客戶端只處理除了所有javax.persistence.PersistenceException之外的自定義應用程序定義的異常。 – veilsoen 2011-03-25 08:30:29