Jpa 使用EJB3.0和CMP时处理约束冲突的最佳方法

Jpa 使用EJB3.0和CMP时处理约束冲突的最佳方法,jpa,ejb-3.0,jax-ws,Jpa,Ejb 3.0,Jax Ws,我有一个web服务(使用jaxb/jaxws构建),它调用无状态EJB在数据库中存储一些数据。数据被存储为实体bean。实体bean通过@列(unique=true)注释对其应用了唯一约束 当web服务试图保存数据时,事务失败,这是理所当然的。问题是,由于我使用的是CMP,所以直到调用无状态EJB之后,事务才会提交。最终的结果是,我无法捕获异常,它将被引导到WS堆栈,并导致包含以下字符串的不明确错误:Error committing transaction:;嵌套异常为:weblogic.tra

我有一个web服务(使用jaxb/jaxws构建),它调用无状态EJB在数据库中存储一些数据。数据被存储为实体bean。实体bean通过
@列(unique=true)
注释对其应用了唯一约束

当web服务试图保存数据时,事务失败,这是理所当然的。问题是,由于我使用的是CMP,所以直到调用无状态EJB之后,事务才会提交。最终的结果是,我无法捕获异常,它将被引导到WS堆栈,并导致包含以下字符串的不明确错误:
Error committing transaction:;嵌套异常为:weblogic.transaction.internal.AppSetRollbackOnlyException

是否有方法捕获抛出的异常,以便我可以向调用方提供更多信息?多谢各位

版本信息:

  • 应用服务器:Oracle Weblogic 10.3
  • 持久性提供程序:Hibernate3.2.5.ga(JPA1.0)
  • JDK/JRE:1.6_0_05(由Weblogic安装提供)
更新: 我试图围绕方法调用实现EJB3拦截器,但这似乎不起作用

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);
    }

}
我认为这不起作用的原因是处理链使得实际的持久化发生在方法之外(当然)。它与JPA(在预持久化、预更新和预删除阶段调用)连接良好,可以在应用程序的不同层中使用

不幸的是,据我所知,如果发生验证约束冲突,事务将被标记为回滚…我不知道您如何处理该问题,但有一个问题(看起来很糟糕,未经测试)我可以想到的方法是注入一个ValidatorFactory,然后自己验证这个对象。也许然后您就可以捕获ValidationException了

编辑:我不确定Java EE 5中是否提供了Bean验证


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

我不熟悉Bean验证,但在我看来,即使Bean已验证,但当对象实际持久化到数据库中时,可能已经发生了与唯一字段相关的约束验证,因此问题仍然存在。Bean验证是正确的JEE5中似乎不可用。@babernat是的,正如所说的-Bean验证发生在预*阶段,因此如果您想检查DB约束,您只能在实际访问DB时检查它们。您可能记得,您可以捕获runtimeException并抛出一些与实际操作更相似的
@ApplicationException
您可以在拦截器中这样做,以将其与您的业务逻辑解耦。我尝试了拦截器方法(请参见编辑的问题),但事务似乎是在调用我的拦截器后提交的,因此我无法使用拦截器捕获它。除非我错误地编写了我的拦截器。您可能希望在使用的EntityManager上调用显式刷新。显式刷新EntityManager确实有效,我可以捕获结果异常并处理它。+1和accep泰德回答了我的帮助。