【问题标题】:Postgres Exceptions and javaPostgres 异常和 java
【发布时间】:2014-10-15 13:18:09
【问题描述】:

我正在使用“postgresql-9.3-1102.jdbc3.jar”来连接数据库。 当我有一个例外时,例如一个空值, 我可以使用多种方法来捕获异常。

例如 尝试 { ............} 捕捉(PSQLException seRs){ ......... }

或者

试试 {.......} 捕获(SQLException se){.......}

或者

试试{ .......} 捕捉(异常se){ ........ }

我的目标是在我感兴趣的情况下捕获特定的 SQLState。

例如我想捕获一个字段的无效 NULL 值, Postgress 返回值“23502”SQLState,但在之前的任何“捕获”中我都做不到,因为错误代码是继承的,我无法检查它。

在前面的“捕获”中,我可以使用“.getmessage”,但这对我没有帮助,我想检查 SqlState

感谢您的任何想法。

【问题讨论】:

    标签: java postgresql exception exception-handling


    【解决方案1】:

    捕获SQLExceptoin,然后使用SQLException.getSQLState() 并比较它是否是您想要的。

    catch (SQLException ex) {
       final String ss = ex.getSQLState();
       //... blah blah ...
    }
    

    有关 SQLState 的详细信息,请参阅PostgreSQL error codes。 (虽然大多数状态类别和代码在 DB 中都是标准的,但并非所有 DB 都以相同的方式实现它们并同时抛出它们,并且大多数 DB 都有特定于 DB 的附加功能)。

    没有办法根据 SQLState 捕获异常。不幸的是,您必须抓住它,如果它不是您想要的,则将其包裹并重新扔掉。 (不要不换行就重新抛出,你会丢失原始堆栈)。

    在 JDBC 4 中,您可以捕获 SQLException 的子类,例如 SQLNonTransientException,但前提是 JDBC 驱动程序抛出这些子类。在撰写本文时,PgJDBC 不支持这些,并且总是简单地抛出SQLException,所以如果你试图捕捉它们,你将永远不会捕捉到任何东西。 (欢迎使用补丁!)。


    在现实世界中,您通常对许多不同的错误条件感兴趣,并希望根据它们做不同的事情。

    有点像未经测试的,写在窗口中的东西:

    } catch (SQLException ex) {
      final String ss = ex.getSQLState();
      if (ss.equals("40001") || ss.equals("40P01")) {      
         /* It is a serialization failure or a deadlock abort. Retry the tx. */
         retry_transaction = true;
      } else if (ss.startsWith("08") || ss.startsWith("53")) {
         /* It is a connection error or resource limit. Reconnect and retry. */
         try {
            conn.close();
         } catch (SQLException ex) { 
            logger.log("Error closing suspected bad connection after SQLState " + ss, ex);
         }
         conn = null; /* App knows to reconnect if it sees a null connection */
         retry_transaction = true;
      } else {
         throw new MyAppException(ex);
      }
    }
    

    ...如果您的应用程序在看到空连接时知道要重新连接,并保留它刚刚尝试的事务的记录,以便它可以在循环中重试它,直到它遇到死锁或序列化失败时它成功。

    实际上你会比这更聪明,添加重试的速率限制等。这只是一个简单的例子。


    有关更多详细信息,请在测试可转换性后将异常转换为PSQLException,或者首先将其捕获为PSQLException。然后通过以下方式获取详细信息:

    ex.getServerErrorMessage()
    

    它会为您提供带有详细字段的ServerErrorMessage

    【讨论】:

    • @Graig 非常感谢您的回复,但我忘了告诉您,在我的情况下 ex.getSQLState() 返回“null”,所以我不能使用 SQLState。我不明白为什么会这样。为了帮助你,为了帮助我,我使用 Netbeans 作为 IDE,在调试中我可以看到 se.Cause.Inherit 下的 SQLstate = 23502。 SQLState
    • @EliasElias 听起来这是一个批次的错误。如果您指的是特定错误,而不是一般情况,您应该在问题中显示堆栈跟踪。如果是批处理,您必须 getNextException 获取嵌套异常。
    • @CraigRinger 我面临同样的问题,而且我不在一个批次中。我得到null 作为原因,getNextException() 也返回null
    【解决方案2】:

    使用连接获取sql状态

    DatabaseMetaData dmd = connection.getMetaData();
    int type = dmd.getSQLStateType();
    

    http://docs.oracle.com/javase/7/docs/api/java/sql/Connection.html#getMetaData%28%29 http://docs.oracle.com/javase/7/docs/api/java/sql/DatabaseMetaData.html#sqlStateSQL

    完整示例:

    Connection conn = null;
    try
    {
        String url = "jdbc:postgresql://localhost/yourdb?user=test&password=secret";
        conn = DriverManager.getConnection(url);
        // Some sql query or stuff
    }
    catch (Exception e)
    {
        if (conn != null)
        {
            DatabaseMetaData dmd = conn.getMetaData();
            int type = dmd.getSQLStateType();
            // Do something with this state
        }
    }
    

    【讨论】:

    • 你为什么要这样做,而不是使用e.getSQLState()
    • 是的,你的方式更好看,但我的工作,即使 NullPointerException 被捕获
    猜你喜欢
    • 1970-01-01
    • 2018-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-07
    • 2017-12-01
    • 2014-02-18
    • 1970-01-01
    相关资源
    最近更新 更多