4

我使用默认的 TopLink 持久性管理器在 Glassfish 上使用 EJB3。在 Session Bean 中,当持久性管理器捕获 DB 异常时,它会将事务标记为回滚,并抛出 EJBException,进而包装 RollbackException。现在我期待能够从这些异常之一的异常中得到原始的 jdbc 异常,但事实并非如此。

检索原始异常很重要,因为我需要向用户报告问题所在,为此我需要分析 SQL 错误代码。

有谁知道是否可以从 Toplink 获得这些信息?或者 Hibernate 是否使它成为可能?

谢谢,

4

4 回答 4

3

我遇到过同样的问题。我最终使用了 AroundInvoke 拦截器方法,这样您就可以在服务器端捕获任何异常,并提取您想要的任何信息并将其包装以抛出您自己的异常,并设置 EjbContext 以回滚事务。

如果您不正确,我可以为您提供示例。

于 2009-10-05T06:53:17.370 回答
1

好问题,蚂蚁

我知道您想抛出数据库异常,但是当它发生时,应用程序在大多数情况下无法恢复其初始状态,或者它不知道如何从中恢复。所以应该作为运行时异常处理。数据库异常中的一些问题包括

  • 数据库连接失败
  • 查询错误
  • 表或列不存在

上面您看到应用程序无法恢复其初始状态。如果您认为有可能恢复其初始状态,那么您应该使用应用程序异常。客户端将获得您的业务方法引发的相同应用程序异常。如果您希望能够获得业务方法抛出的确切异常,您有两种选择:

  • 使用业务委托模式访问您的 EJB

如您所知,运行时异常由 EJBException 包装,因此您应该使用类似

假设您有这个无状态会话 bean

@Stateless
public class BeanImpl implements Bean {

    public void doSomething() {

        try {
            // some code
        } catch(SomeException e) {
            throw new EJBException(e);
        }

    }        

}

因此,您通过业务委托包装您的会话 bean

public class BeamBusinessDelegate implements Bean {

    // your stateless session bean goes here
    private Bean bean;

    public BeamImpl() {
        InitialContext i = new InitialContext();

        bean = (Bean) i.lookup(<GLOBAL_JNDI_ADDRESS_OR_RELATIVE_ENVIRONMENT_NAMING_CONTEXT_ADDRESS>);
    }

    public void doSomething() {
        try {
            bean.doSomething()
        } catch(EJBException e) {
            throw e.getCause();
        }
    }
}

或者您可以根据需要扩展 EJBException

public class DatabaseException extends EJBException {

}

所以在你的商业方法中

@Stateless
public class BeanImpl implements Bean {

    public void doSomething() {

        try {
            // some code
        } catch(SomeException e) {
            throw new DatabaseException();
        }

    }        

}

问候,

于 2009-10-03T18:22:02.750 回答
1

我发现做我想做的唯一方法是强制经理使用 manager.flush() 写入数据库,然后捕获抛出的 PersistenceException。然后我可以根据需要记录数据库错误,并抛出 EJBException 以强制回滚。离开容器进行刷新似乎无法挽回地丢失 TopLink 的任何有用消息。

于 2009-10-13T09:28:54.910 回答
1

我有同样的问题:如何获取从 JPA 生成的 SQL 错误消息?

我也没有找到解决方案,但是我在我的 persistence.xml 中添加了这一行

    <properties>
        <property name="toplink.logging.level" value="FINE" />
    </properties>

现在,我可以看到发出的 sql 命令。

参考: http ://www.jairrillo.com/blog/2008/09/04/introduction-to-jpa-part-1-getting-started/

于 2009-10-27T04:12:40.470 回答