EJB3 获取原始 JDBC 错误

发布于 2024-08-07 04:22:05 字数 292 浏览 9 评论 0原文

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

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

有谁知道是否可以从 Toplink 获取此信息?或者 Hibernate 是否使之成为可能?

谢谢,

I am using EJB3 on Glassfish using the default TopLink persistance manager. Within a Session Bean, when the persistence manager catches a DB exception, it marks the transaction to be rolled back, and throws an EJBException, in turn wrapping a RollbackException. Now I was expecting to be able to get the original jdbc exception out of the caused by exception of one of these exceptions, but it is not.

It is important that I do retrieve the original exception, as I need to report back to the users what the problem is, and to do this I need to analyse the SQL error codes.

Does anyone know if it is possible to get this information from Toplink? Or whether Hibernate makes it possible?

Thanks,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

时光暖心i 2024-08-14 04:22:06

好问题,Ant,

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

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

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

  • 使用业务委托模式来访问您的 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();
        }

    }        

}

方面,

Good question, Ant

I know you want to throw a database exception but when it occurs the application, in most of the time, is not able to restore its initial state or it does not know how to recover from it. So it should be handled as a runtime exception. Some problems in database exceptions includes

  • database connection failure
  • query is wrong
  • table or column does not exist

Above you see the application is not be able to restore its initial state. If you think it is possible restore its initial state so you should use a application exception. Client will get the same application exception thrown by your business method. If you want to be able to get the exact exception thrown by your business method you have two choices:

  • Use a business delegate pattern to access your EJB

As you know, runtime exception is wrapped by a EJBException, so you shold use something like

Let's suppose you have this Stateless session bean

@Stateless
public class BeanImpl implements Bean {

    public void doSomething() {

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

    }        

}

So you wrap your session bean through a business delegate

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

Or you can extends EJBException according to your needs

public class DatabaseException extends EJBException {

}

So in your business method

@Stateless
public class BeanImpl implements Bean {

    public void doSomething() {

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

    }        

}

regards,

苦笑流年记忆 2024-08-14 04:22:06

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

The only way I've found to do what I want, is to force the manager to write to the db using manager.flush(), and then catch the PersistenceException that that throws. I can then log the database error as I want, and throw an EJBException to force rollback. Leaving the container to do the flush seems to irretrievably lose any useful messages with TopLink.

浅笑依然 2024-08-14 04:22:06

我有同样的问题:如何获取从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/

I have the same question : how to get the SQL error message generated from JPA?

I haven't found the solution either but, I added this line in my persistence.xml

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

and now, I can see the sql commands issued.

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

叹梦 2024-08-14 04:22:05

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

如果你不明白的话我可以给你举个例子。

I had the same issue. I ended up using the AroundInvoke interceptor method , that way you can catch any exception on the server side , and extract whatever info you want to and wrap it to throw your own exception , and set the EjbContext to rollback the transaction.

I can provide you with an example if you don't come right.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文