当前位置: 首页 > 知识库问答 >
问题:

为什么TRY CATCH成功更新SSMS上的行,但在从Tomcat应用程序运行时没有?

孙宏壮
2023-03-14

我在Azure的SQL上有一个TSQL过程。这是一个最小的可重复的例子。

CREATE PROCEDURE MyPROC
AS
BEGIN
    BEGIN TRY
        SELECT 1/0
    END TRY
    BEGIN CATCH
        UPDATE error_log SET error_desc='test'
    END CATCH
END

直接从 SSMS 运行时,error_log已成功更新。

当从我的Tomcat应用程序(使用Tomcat用户)运行时,程序被执行,但是< code>error_log没有更新。

雄猫使用以下 Java 代码执行该过程

    DBConnection dbConn  = DBConnection.getInstance();
    Connection conn = null;
    try {
        conn = dbConn.getConnection();
        conn.setAutoCommit(false);
        CallableStatement stmt = conn.prepareCall("{CALL MyPROC}");
        stmt.execute();
        result = stmt.getInt(fields.size());
        if (result == DBProcedures.RESULT_FAILED) { // error
            conn.rollback();
        } else { // ok
            conn.commit();
        }
    } catch (SQLException e) {
        result = DBProcedures.RESULT_FAILED;
        try {
            conn.rollback();
        } catch (SQLException e1) {
            System.out.println("Exception on " + this.toString() + " " + e.toString());
        }
        System.out.println("Exception on " + this.toString() + " " + e.toString());
    } finally {
        try {
            conn.setAutoCommit(true);
        } catch (SQLException e) {
            System.out.println("Exception on " + this.toString() + " " + e.toString());
        }
        dbConn.returnConnection(conn);
    }

我已经检查了Tomcat用户对<code>error_log<code>表的权限。

我错过了什么?我知道并非所有错误都被TRY CATCH捕获,并且我知道有时事务无法执行任何会生成写入操作的事务处理 SQL 语句。但是,我的例子似乎不属于这两类中的任何一类。此外,它在SSMS下确实有效。

共有1个答案

薛经纶
2023-03-14

这是由于< code>auto_commit设置为off,这意味着驱动程序执行命令< code > SET IMPLICIT _ TRANSACTIONS ON;

你可以在小提琴上看到这一点。

为了解决这个问题,您可以先显式回滚原始事务。理想情况下,您还应该使用XACT_ABORT来防止挂起事务,并使用THROW重新抛出原始错误。

CREATE PROCEDURE MyPROC
AS
BEGIN
    SET XACT_ABORT ON;

    BEGIN TRY
        SELECT 1/0;
    END TRY
    BEGIN CATCH
        IF @@TRANCOUNT > 0
            ROLLBACK;

        UPDATE error_log SET error_desc = 'test';

        THROW;  -- only if you want the error to propagate back to Tomcat
    END CATCH;
END;

坦率地说,我不建议使用< code>BEGIN CATCH来记录错误,因为不是所有的错误都是可捕捉的。而是使用SQL Server错误日志或XEvent会话来记录错误。

 类似资料:
  • 我有一个JavaFX应用程序,它调用一些JNI代码,使用预加载程序jar,并使用JDK1.7编译。现在,当我使用JRE7在另一台计算机上运行jar时,通过: 双击jar:它启动,但无法加载包含库的JNI代码,因此被卡住。 有人能告诉我这三种情况有什么不同吗?

  • 我使用log4j2,但我的一些依赖项使用log4j。当我从一个可执行jar文件运行应用程序时,我只得到几行日志和以下消息: 但当我在IntelliJ内部运行应用程序时,它会按预期工作,不会产生任何警告和所有日志。 我用maven enforcer来禁止log4j。我还尝试添加依赖项,但将范围设置为“提供”。 我也用一个版本号而不是一个范围来完成上面的工作。当应用程序在IntelliJ中运行时,所有

  • 目标是从IP地址列表中阻止对页面的访问。此列表位于文件列表中。txt。我提供了一个服务,可以检查来自请求的IP,并使用“不需要的”地址的哈希集,但子目标是这个列表中的“即时捕获”。txt。我的意思是:如果我向这个文件添加了一些IP,它应该在不重新启动应用程序的情况下被阻止。我不知道如何解决这个问题,因为我的应用程序只有在重启后才会刷新这个列表。我的代码在下面 和控制器: 有人能帮忙完成这个“子目标

  • 我在CompletableFuture的供应Async()中处理长时间运行的操作,并将结果输入thenAccess()。在某些情况下,thenAccess()在主线程上执行,但在某些时候,它在工作线程上运行。但是我想只在主线程上运行thenAccess()操作。这是示例代码。 结果是: 我怎样才能解决这个问题?

  • 关于我以前的问题,我在Linux上运行企业级web应用程序时遇到了一些问题。在投资一台真正的登台机之前,我想我应该在Raspbery Pi上试一试,但现在,我们在一台真正的Debian计算机上运行该应用程序。 这个问题和我前面的问题一样。 起初,我认为这更像是tomcat的问题,但现在,我认为这是一个 <罢工> 覆盆子皮 Linux问题。 我将Spring bean定义为; 它给了我,说明没有定义

  • 所以我超级兴奋,我终于想出了这个程序,然后砰的一声启动它=空白屏幕。我在这里调用一个空白窗格,而其他信息没有填充吗?它是在屏幕外填充的吗?出于某种原因,JavaFX真的让我动心了。如果有人也有什么好的地方去读它。(我知道谷歌很管用,我找到的很多网站/地方都不适合我。