Exception和SQLException之间的区别

时间:2014-04-08 18:11:19

标签: java sql exception exception-handling sqlexception

有人可以解释捕获Exception和捕获SQLException之间的区别吗?我知道如果您选择打印出异常错误,SQLException会打印出更多信息,但还有其他什么吗?

try {
   //code
} catch(Exception ex) {
   //code
}

try {
   //code
} catch(SQLException ex) {
   //code
}

在catch块中使用ExceptionSQLException有什么好处和不同?

10 个答案:

答案 0 :(得分:3)

这不是唯一的区别。

捕获Exception是危险的,因为它还会捕获所有RuntimeException(因此未经检查的异常),并且包括明确的程序员错误等NullPointerException等细节。 不要那样做

此外,Exception是一个类似于任何其他的类,因此您可以将其子类化并添加您的构造函数/方法。例如,SQLException有一个.getErrorCode() method Exception没有。如果您只捕获Exception,则无法访问此方法。

总的来说,抓住更准确的"异常首先是最好的。例如,使用新的(在Java 7 ...中)文件API,您可以轻松区分文件系统级错误和其他I / O错误,因为FileSystemException扩展了IOException

try {
    something();
} catch (FileSystemException e) {
    // fs level error
} catch (IOException e) {
    // I/O error
}

答案 1 :(得分:3)

当你在谈论捕捉异常时,这完全是关于层次结构的。

从技术上讲,Exception - 是捕获每个异常的超类。 如果你在try块中编写与SQL相关的东西,你知道它甚至可能抛出SQL Exception。     然后你也可以用这种方式声明它。

        try
        {

        }catch(SQLException ex)
        {
        Do this,when SQL Exception is caught.
        }
        catch(Exception ex)
        {
        Generic Exception - works for all
        }

答案 2 :(得分:1)

SQLException继承自Exception,因此SQLException将包含比Exception更多(更具体)的信息(通常用于所有例外)。< / p>

您还可以拥有多个catch条款;所以你可以先试着抓住SQLException,但如果它不是SQLException,那么你就可以抓住将军Exception

一般情况下,除非您打算以某种方式处理它们,否则不应该catch例外。你可以拥有一个顶级异常处理程序来捕获任何异常,这些异常会冒泡到调用堆栈的顶部,这样你的程序就不会因未处理的异常而崩溃。

答案 3 :(得分:1)

A - 解释

SQLExceptionjava.lang.Exception的子类型,并且它正在实施Iterable<Throwable>类。程序员更喜欢抛出Exception类的不同子类型,因为在更高级别上,他们希望捕获确切的子Exception类,以便他们可以确保在某些确切的场景中抛出该特定的Exception。因此,他们可以知道Exception的确切来源。

B - 示例

考虑您编写了一个抛出多个异常的方法。让我们说,你拿一个json String并解析它,然后将它保存在数据库中。考虑以下方法;

public boolean persistCustomer(String jsonString) throws SQLException, IOException {
    Connection conn = getConnection(); 
    PreparedStatement preparedStatement = null;


    ObjectMapper objectMapper = new ObjectMapper();
    try {
        Customer customer = objectMapper.readValue(jsonString, Customer.class);

        preparedStatement = conn.prepareStatement(PERSIST_CUSTOMER);

        preparedStatement.setString     (1,  customer.getName());
        preparedStatement.setInt        (2,  customer.getAge());
        preparedStatement.setBoolean    (3,  customer.getIsRegular());

        preparedStatement.executeUpdate();

        return true;
    } catch (IOException e) {
        throw e;
    } finally {
        try {
            if (preparedStatement != null)
                preparedStatement.close();
            if (conn != null)
                conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

在此方法中,我们将JSON转换为Customer类,并且我们还将客户类保留到数据库中。

以下行抛出SQLException;

    preparedStatement = conn.prepareStatement(PERSIST_CUSTOMER);

    preparedStatement.setString     (1,  customer.getName());
    preparedStatement.setInt        (2,  customer.getAge());
    preparedStatement.setBoolean    (3,  customer.getIsRegular());

    preparedStatement.executeUpdate();

prepareStatement(),制定者和executeUpdate()方法,所有这些方法都在投放SQLException。但是,我们将String中的JSON转换为Customer对象的行也会抛出除SQLException之外的几个异常。

Customer customer = objectMapper.readValue(jsonString, Customer.class);

readValue()方法会引发JsonParseExceptionJsonMappingExceptionIOException。所有这些都可以使用IOException进行捕获,因为与JSON相关的异常会扩展IOException

我将提供两个不同的示例,以便明白为什么我们需要不同类型的例外。

C - 不良做法:使用例外来捕获所有例外

public class BadPracticeExample {

    public static void main(String[] args) {
        MySQLUtil dbUtil =  new MySQLUtil();

        String jsonString = "{\"name\":\"Levent\",\"age\":31,\"isRegular\":true}";

        try {
            dbUtil.persistCustomer(jsonString);
        } catch (Exception e) {
            System.out.println("A problem occured");
        }
    }

}

正如您所看到的,它捕获了Exception,但如果我们需要针对两个不同的问题来源进行特殊的异常处理,我们该怎么做? persistCustomer可以抛出IOException或SQLException,如果我们需要执行不同的任务来处理这些问题呢?我想在发生SQLException时向数据库管理员发送一封电子邮件,并且我想在发生JSON解析问题时继续发送,如果捕获到IOException?

在这种情况下,您无法做到这一点。以下是上面代码段的输出,我们只确定发生了异常,但我们不知道它的来源是什么;

A problem occured

D - 良好实践示例I:SQL异常捕获

public class GoodPracticeExample {

    public static void main(String[] args) {
        MySQLUtil dbUtil =  new MySQLUtil();

        String jsonString = "{\"name\":\"Levent\",\"age\":31,\"isRegular\":true}";

        try {
            dbUtil.persistCustomer(jsonString);
        } catch (SQLException e) {
            System.out.println("SQL Exception catched, SQL State : " + e.getSQLState());
            System.out.println("Error Code                       : " + e.getErrorCode());
            System.out.println("Error Message                    : " + e.getMessage());
        } catch (IOException e) {
            System.out.println("Cannot parse JSON : " + jsonString);
            System.out.println("Error Message     : " + e.getMessage());
        }
    }

}

正如您所看到的,我们同时捕获了JSON和SQL问题,在此示例中,submethod尝试将DB保留在没有表的位置。输出如下;

SQL Exception catched, SQL State : 42000
Error Code                       : 1142
Error Message                    : INSERT command denied to user 'levent'@'example.com' for table 'CUSTOMER'

因此我们捕获了SQL Exception,并且我们拥有发送警报电子邮件所需的所有参数。我们可以在SQLException catch块上添加额外的处理程序或实用程序方法。

D - 良好实践示例II:IOExceptoin捕获解析错误

public class GoodPracticeExample {

    public static void main(String[] args) {
        MySQLUtil dbUtil =  new MySQLUtil();

        String jsonString = "{\"Zname\":\"Levent\",\"age\":31,\"isRegular\":true}";

        try {
            dbUtil.persistCustomer(jsonString);
        } catch (SQLException e) {
            System.out.println("SQL Exception catched, SQL State : " + e.getSQLState());
            System.out.println("Error Code                       : " + e.getErrorCode());
            System.out.println("Error Message                    : " + e.getMessage());
        } catch (IOException e) {
            System.out.println("Cannot parse JSON : " + jsonString);
            System.out.println("Error Message     : " + e.getMessage());
        }
    }

}

如果您已经注意到,我已经损坏了JSON以导致IOException。现在在json字符串中,而不是&#34; name&#34;,&#34; Zname&#34;写的会导致Jackson Parser失败。我们来看看这段代码的输出。

Cannot parse JSON : {"Zname":"Levent","age":31,"isRegular":true}
Error Message     : Unrecognized field "Zname" (class com.divilioglu.db.utils$Customer), not marked as ignorable (3 known properties: "isRegular", "name", "age"])
 at [Source: (String)"{"Zname":"Levent","age":31,"isRegular":true}"; line: 1, column: 11] (through reference chain: com.divilioglu.db.utils.MySQLUtil$Customer["Zname"])

正如您所看到的,我们捕获了特定的场景,我们确信,这来自dbUtil.persistCustomer()方法中的行,如下所示;

Customer customer = objectMapper.readValue(jsonString, Customer.class);

E - 结论

因此,最佳做法是通过扩展现有的Exception类来创建新的Exceptions。在编写代码时,您可能会认为它是一种过度杀伤并且您不需要额外的异常类,但是当您需要区分问题的根源并独立处理它们时,您将需要它们。

在上面演示的这个示例中,我可以独立地捕获IOExceptionSQLException,并且两个异常的来源都来自同一个方法。我想区分两者,以便我可以独立处理它们。如果只是使用基本Exception类包装所有异常,则不能具有这种灵活性。

答案 4 :(得分:0)

Exception是一个标准类,每个例外都会从该类继承。

SQLException是一个继承自Exception的类,专门为数据库(SQL)异常而设计。

通过

try {
    // Your code here
} catch (Exception e) {
    // Catching here
}

您正在捕捉各种类型的异常......但是,您可能无法知道如何对特定异常做出反应。

但是做了

try {
    // Your code here
} catch (SQLException e) {
    // Catching here
}

您知道在处理数据库时发生了异常,它可以帮助您了解如何对异常做出反应。

答案 5 :(得分:0)

如您所见SQLException扩展异常。所以这才是唯一的区别。当您捕获异常时,您将捕获所有异常(这是不好的)。但是当你捕获SQLException然后你只捕获它(这很好,因为这是你正在寻找的)。

答案 6 :(得分:0)

如果抛出try和catch块之间的异常,这不是SQL异常(这些异常通常只来自与数据库相关的代码),例如Null Pointer Exception,Exception catch会捕获它,但是SQLException不会。

答案 7 :(得分:0)

SQLException是一个异常,所以你只是得到一个更具体的异常。

根据Oracle的javadocs,您获得的具体信息是:

  • 描述错误的字符串。这用作Java异常 消息,可通过getMessage方法获得。
  • a&#34; SQLstate&#34;字符串,它遵循XOPEN SQLstate 约定或SQL:2003约定。 SQLState的值 字符串在适当的规范中描述。 DatabaseMetaData 方法getSQLStateType可用于发现是否有驱动程序 返回XOPEN类型或SQL:2003类型。
  • 特定于每个供应商的整数错误代码。通常这个 将是底层数据库返回的实际错误代码。
  • 链接到下一个例外。这可以用来提供额外的 错误信息。
  • 这个SQLException的因果关系,如果有的话。

答案 8 :(得分:0)

SQLException是源自Exception的专门例外。

如果你抓住Exception,所有异常都会被抓住。甚至是不受欢迎的例外。

如果你只抓住它的特殊性,SQLException,只有SQLException本身或其衍生物才会被捕获。

只能抓住一个人可以处理或希望处理的异常,并让其他人冒泡。

如需进一步参考,请查看以下内容:

  1. Exception
  2. SQLException

答案 9 :(得分:0)

使用Java数据库连接(JDBC)时,SQL异常是一个经常出错的错误。它与使用预准备语句访问或设置SQL查询中的列有关。

SQLException派生自Exception,包含与访问或设置SQL查询中的列相关的更多特定信息,而异常通常更为通用。