说我有以下部署为本地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