使用EJB 3.0和CMP时处理约束违规的最佳方法

时间:2011-11-03 14:45:26

标签: jpa ejb-3.0 jax-ws

我有一个Web服务(使用jaxb / jaxws构建),它调用无状态EJB来在数据库中存储一些数据。数据存储为实体bean。实体bean具有通过@Column(unique = true)注释应用于它的唯一约束。

当Web服务尝试保存数据时,事务失败,这是正确的。问题是因为我使用CMP,所以直到调用无状态EJB之后才会提交事务。最终结果是我无法捕获异常,并且它正在进入WS堆栈并导致包含字符串的模糊错误:Error committing transaction:;nested exception is: weblogic.transaction.internal.AppSetRollbackOnlyException

有没有办法捕获抛出的异常,以便我可以向调用者提供更多信息?谢谢。

版本信息:

  • Application Server:Oracle Weblogic 10.3
  • 持久性提供程序:Hibernate 3.2.5.ga(JPA 1.0)
  • JDK / JRE:1.6_0_05(由Weblogic安装提供)

更新: 我尝试围绕方法调用实现EJB 3拦截器,但这似乎不起作用。

public class TestInterceptor {

@AroundInvoke
public Object logCall(InvocationContext context) throws Exception {

    System.out.println("Invoking method: " + context.getMethod().getName());

    try {
        return context.proceed();
    } catch (Throwable t) {
        System.out.println("I caught an exception: " + t.getMessage());
        throw new Exception(t);
    }

}

我认为这不起作用的原因是因为处理链是实际的持久性发生在方法之外(当然)。

1 个答案:

答案 0 :(得分:2)

您可以尝试使用Bean Validation。它与JPA很好地连接(在预先保留,预更新和预删除阶段调用,可以在应用程序的不同层中使用。

不幸的是,据我所知,如果发生了验证约束违规,则事务被标记为回滚...我不知道你是如何应对的但是一个(看起来很讨厌且未经测试)我想到的方法是注入一个ValidatorFactory并自己验证对象。也许那时你可以捕获ValidationException。

编辑:我不确定Bean验证是否在Java EE 5中可用。

编辑2:您可以创建一个拦截器来捕获JPA抛出的异常(或者更准确地说是由数据库引发的异常)。由于拦截器作为EJB方法的同一事务的一部分被调用,您可能需要显式调用EntityManager#flush( - )以使更改与数据库同步。