java 为什么 SQLException 是已检查的异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16543605/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 23:16:15  来源:igfitidea点击:

Why is SQLException a checked exception

javaexceptioncoding-stylecheckedunchecked

提问by Bohemian

Can anyone think of a rational reason why SQLExceptionis a checkedexception?

任何人都可以想到一个合理的原因为什么SQLException受检异常?

Yes, there could be a syntax error in the query
Yes, the connection might have died
Yes, there might be a permission problem
Etc, etc blah blah blah

是的,查询中可能存在语法错误
是的,连接可能已经死亡
是的,可能存在权限问题
等等等等等等

But practically 100% of the time (once you're running in production), there isn't any problem.

但实际上 100% 的时间(一旦您在生产中运行),没有任何问题。

If there is a problem, the calling code can't do anything to recover, so for that reason it should be unchecked.

如果出现问题,调用代码将无法进行任何恢复,因此应取消选中它。

Being checked create masses of perfunctory try catchblocks throughout the code, as anyone who has been involved with a project that uses JDBC will attest. The code clutter is significant.

被检查会try catch在整个代码中创建大量敷衍的块,任何参与过使用 JDBC 的项目的人都会证明这一点。代码混乱很重要。

Because of the esoteric nature of SQL, the myriad of reasons you may get an SQLException and their complexity means you basically can not recover, unless the exception is caused by temporary network problem, but even then in a synchronous call, you're sunk anyway because you can't wait indefinitely for the network problem to be resolved, so you're going to have to fail the transaction.

由于 SQL 的深奥性质,您可能会收到 SQLException 的无数原因及其复杂性意味着您基本上无法恢复,除非该异常是由临时网络问题引起的,但即使在同步调用中,您仍然会沉没因为您不能无限期地等待网络问题得到解决,所以您将不得不使交易失败。

Typically, calling SQL looks like this:

通常,调用 SQL 如下所示:

try {
    // make some SQL call(s)
} catch {SQLException e) { 
    // log the exception
    return; // and give up
}

Such code adds no value. There nothing reasonable you can do to recover. You might as well let a runtime exception bubble up - ie SQLException should be a runtime(unchecked) exception.

这样的代码没有任何价值。您无法采取任何合理的措施来恢复。您不妨让运行时异常冒泡——即 SQLException 应该是运行时(未经检查的)异常。

回答by Bohemian

practically 100% of the time there isn't any problem- This is limited to your own observation which says nothingabout other systems. There are various computer systems around the world with various bottlenecks. Your success rate is almost 100%. Others have to deal with much lower percentage.

几乎 100% 的时间都没有任何问题- 这仅限于您自己的观察,对其他系统没有任何说明。世界上有各种各样的计算机系统,它们有各种各样的瓶颈。你的成功率几乎是 100%。其他人必须处理低得多的百分比。

Common misconceptionis to consider introducing/removing a Checked Exception by frequencyof its occurrence. Checked exceptions serve as communication channels. As you know, every method has its public interface. This way, method tells us which arguments it accepts and what is result of the code in its body.

常见的误解是考虑通过检查异常的发生频率来引入/删除检查异常。检查异常作为通信渠道。如您所知,每个方法都有其公共接口。通过这种方式,method 告诉我们它接受哪些参数以及它主体中的代码的结果是什么。

When it becomes impossible for a method currently being in progress to keep its promise (e.g. returned value) it needs a way to tell the other method that something went wrong and it can't do what was expected. But how to do it ? Sending the message as the value returned doesn't work, there is almost no chance for the calling method to distinguish between proper value and an error message. Not to say some methods have void as a return value. So what do you do when you're unable to keep your promise defined by your method's interface ? Well, you throw an exception (send a message).

当当前正在进行的方法无法兑现其承诺(例如返回值)时,它需要一种方法来告诉另一个方法出现问题并且它无法执行预期的操作。但是怎么做呢?将消息作为返回值发送不起作用,调用方法几乎没有机会区分正确的值和错误消息。并不是说某些方法将 void 作为返回值。那么,当您无法遵守方法接口定义的承诺时,您会怎么做?好吧,您抛出异常(发送消息)。

If you expect ResultSet and there is no connection to your database established, what should you do ? Return empty ResultSet ? Hell no, this tells us that the database is empty. Return null ? Well, this only delegates the problem and makes finding the cause unclear.

如果您期望 ResultSet 并且没有与您的数据库建立连接,您应该怎么做?返回空的结果集?地狱不,这告诉我们数据库是空的。返回空值?嗯,这只会代表问题,并使查找原因不清楚。

You could use that empty resultset and make it a part of another query to another database, making it inconsistent.

您可以使用该空结果集并将其作为对另一个数据库的另一个查询的一部分,使其不一致。

Without SQLException, even one mistake could lead to data inconsistency.

如果没有 SQLException,即使是一个错误也可能导致数据不一致。

回答by Christopher Gillis

Catching exceptions grant us the ability to recover from exceptional conditions, true, but they also allow us to do other things.

捕获异常使我们能够从异常情况中恢复,这是真的,但它们也允许我们做其他事情。

You cannot recover from a SQLException in that there isn't much you can do to fix the problem at run time, but there are some useful things you can do:

您无法从 SQLException 中恢复,因为您无法在运行时修复问题,但您可以做一些有用的事情:

  • Log the exception for debugging information
  • Rollback a transaction
  • 记录调试信息的异常
  • 回滚事务

You could always log the exception at a higher level (or lower, depending on perspective), but you lose some semantic value, both at debugging time and when reviewing the code.

您总是可以在更高级别(或更低,取决于视角)记录异常,但是在调试时和查看代码时都会丢失一些语义价值。

If you do something like:

如果您执行以下操作:

try { ... }
catch(SQLException e) 
{ 
    SomeLogger.log(...);
    rollback();
    throw e;
}

and come back to this code later, you'll instantly realize that the code in the try can fail without having to mentally parse the code to determine if it can fail.

稍后再回到这段代码,您会立即意识到 try 中的代码可能会失败,而无需仔细分析代码以确定它是否会失败。

Another thing you could do is ensure any database resources have been released, though I'm not sure if this can happen off hand.

您可以做的另一件事是确保已释放所有数据库资源,但我不确定这是否会发生。

回答by Adam Siemion

There are a couple of approaches to the checked vs unchecked dilemma. Checking if the calling code can recover from the exception or not is one approach, this one however, I agree, does not explain why SQLExcptionis a checkedexception.

有几种方法可以解决受检查与不受检查的困境。检查调用代码是否可以从异常中恢复是一种方法,但是我同意这种方法并没有解释为什么SQLExcption受检异常。

Another one, provided by Martin Fowler in his great book "Refactoring" suggests to verify wether it is the callingor the calledmethod responsibility to make a check that might result in an exception.

另一个由 Martin Fowler 在他的伟大著作“重构”中提供的建议验证是调用方法还是被调用方法负责进行可能导致异常的检查。

If the callermethod should perform a check prior calling the calledmethod (e.g. making sure the arguments are not not null) then if this check has not been done it is clearly a programming error and then the calledmethod should thrown an uncheckedexception.

如果调用方方法应该在调用被调用方法之前执行检查(例如确保参数不为空),那么如果没有执行此检查,则显然是编程错误,然后被调用方法应该抛出未经检查的异常。

Now if it is the calledmethod responsibility to make the check, because only this method can know how to perform such check then the exception thrown from the calledmethod should be checked.

现在如果是被调用的方法负责进行检查,因为只有这个方法才能知道如何执行这种检查,那么应该检查从被调用方法抛出的异常。

In case of SQLExceptionI think only this class can know:

如果SQLException我认为只有这个班级可以知道:

  • there is a syntax error in the query as this depends on the database
  • the connection has died
  • there is a permission problem
  • 查询中有语法错误,因为这取决于数据库
  • 连接已死
  • 存在权限问题

回答by obourgain

One reason would be that a method should throw exception which are consistent with the abstraction level of what the method does.

一个原因是方法应该抛出与方法所做的抽象级别一致的异常。

So a method which loads information from a database should not raise a SQLException, but rather a ResourceNotFoundExceptionor a ResourceUnavailableException.

因此,从数据库加载信息的方法不应引发 a SQLException,而应引发aResourceNotFoundException或 a ResourceUnavailableException

Making the SQLExceptionchecked is a way to force the developper to catch the Exception and wrap it in this new level of abstraction.

进行SQLException检查是一种强制开发人员捕获异常并将其包装在这个新的抽象级别的方法。

This argument is taken from Effective Java Second Edition by Joshua Bloch (Item 61: Throw exceptions appropriate to the abstraction).

该论点取自 Joshua Bloch 的 Effective Java Second Edition(第 61 项:适合抽象的抛出异常)。