有人可以解释捕获Exception
和捕获SQLException
之间的区别吗?我知道如果您选择打印出异常错误,SQLException会打印出更多信息,但还有其他什么吗?
try {
//code
} catch(Exception ex) {
//code
}
和
try {
//code
} catch(SQLException ex) {
//code
}
在catch块中使用Exception
和SQLException
有什么好处和不同?
答案 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)
SQLException
是java.lang.Exception
的子类型,并且它正在实施Iterable<Throwable>
类。程序员更喜欢抛出Exception
类的不同子类型,因为在更高级别上,他们希望捕获确切的子Exception类,以便他们可以确保在某些确切的场景中抛出该特定的Exception。因此,他们可以知道Exception的确切来源。
考虑您编写了一个抛出多个异常的方法。让我们说,你拿一个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()
方法会引发JsonParseException
,JsonMappingException
和IOException
。所有这些都可以使用IOException
进行捕获,因为与JSON相关的异常会扩展IOException
。
我将提供两个不同的示例,以便明白为什么我们需要不同类型的例外。
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
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块上添加额外的处理程序或实用程序方法。
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);
因此,最佳做法是通过扩展现有的Exception类来创建新的Exceptions。在编写代码时,您可能会认为它是一种过度杀伤并且您不需要额外的异常类,但是当您需要区分问题的根源并独立处理它们时,您将需要它们。
在上面演示的这个示例中,我可以独立地捕获IOException
和SQLException
,并且两个异常的来源都来自同一个方法。我想区分两者,以便我可以独立处理它们。如果只是使用基本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,您获得的具体信息是:
答案 8 :(得分:0)
SQLException
是源自Exception
的专门例外。
如果你抓住Exception
,所有异常都会被抓住。甚至是不受欢迎的例外。
如果你只抓住它的特殊性,SQLException
,只有SQLException
本身或其衍生物才会被捕获。
只能抓住一个人可以处理或希望处理的异常,并让其他人冒泡。
如需进一步参考,请查看以下内容:
答案 9 :(得分:0)
使用Java数据库连接(JDBC)时,SQL异常是一个经常出错的错误。它与使用预准备语句访问或设置SQL查询中的列有关。
SQLException派生自Exception,包含与访问或设置SQL查询中的列相关的更多特定信息,而异常通常更为通用。