3

哪一个会更好:错误代码或异常情况?

我曾经见过这两种错误处理技术。我不知道每种技术的优缺点。

public void doOperation(Data data) throws MyException {
    try {
        // do DB operation
    } catch (SQLException e) {
        /* It can be ChildRecordFoundException, ParentRecordNotFoundException
         * NullValueFoundException, DuplicateException, etc..
         */
        throw translateException(e);
    }
}

或者

public void doOperation(Data data) throws MyException {
    try {
        // do DB operation
    } catch (SQLException e) {
        /* It can be "CHILD_RECORD_FOUND, "PARENT_RECORD_NOT_FOUND"
         * "NULL_VALUE_FOUND", "DUPLICATE_VALUE_FOUND", etc..
         */
        String errorCode = getErrorCode(e);
        MyException exc = new MyException();
        exc.setErrorCode(errorCode);
        throw exc;
    }
}

对于第二种方法,错误代码检索表单配置文件。我们可以Error Code根据SQL Vender Code.

SQL_ERROR_CODE.properties

#MySQL Database
1062=DUPLICATE_KEY_FOUND
1216=CHILD_RECORD_FOUND
1217=PARENT_RECORD_NOT_FOUND
1048=NULL_VALUE_FOUND
1205=RECORD_HAS_BEEN_LOCKED

方法 1 的调用方客户端

    try {

    } catch(MyException e) {
        if(e instanceof ChildRecordFoundException) {
            showMessage(...);
        } else if(e instanceof ParentRecordNotFoundException) {
            showMessage(...);
        } else if(e instanceof NullValueFoundException) {
            showMessage(...);
        } else if(e instanceof DuplicateException) {
            showMessage(...);
        }
    }

方法 2 的调用方客户端

    try {

    } catch(MyException e) {
        if(e.getErrorCode().equals("CHILD_RECORD_FOUND")) {
            showMessage(...);
        } else if(e.getErrorCode().equals("PARENT_RECORD_NOT_FOUND") {
            showMessage(...);
        } else if(e.getErrorCode().equals("NULL_VALUE_FOUND") {
            showMessage(...);
        } else if(e.getErrorCode().equals("DUPLICATE_VALUE_FOUND") {
            showMessage(...);
        }
    }
4

5 回答 5

6

我推荐使用 Spring 的JDBCTemplate. 它将大多数现有数据库的异常转换为特定的未经检查的异常,例如DataIntegrityViolationException. 它还将在消息中包含原始 SQL 错误。

于 2012-09-19T09:58:24.980 回答
2

奇怪的问题,因为这两种方法都做同样的事情:它们将已检查的 SqlException 转换为似乎未检查的不同异常。所以第一个是更好的,因为它把它变成了一个单一的方法。

两者都留下了一些问题:

  • 是否有一些基础设施可以进行这种转换(另一个答案中提到了 Spring 模板)

  • 你真的想要检查异常吗,在我看来,它们几乎不值得麻烦。

  • 谁在对异常进行真正的处理,它是否获得了所有需要的信息?我通常会期望一些有关在 MyException 中失败的事务的其他信息,例如:我们尝试做什么?(例如更新一个业务对象);在什么样的物体上?(例如一个人);我们/用户如何识别对象(例如 person.id + person.lastname + person.firstname)。如果您想生成日志/错误消息来告诉您或您的用户不仅仅是“糟糕,出了点问题”,您将需要此类信息

  • 为什么 MyException 是可变的(至少在第二个示例中)

于 2012-09-19T10:14:40.043 回答
1

比任何一个更好的设计是通过扩展来使您的自定义异常不受检查RuntimeException

我希望您的异常包含第一个异常,因此以这种方式编码也会更好:

MyException exception = new MyException(e); // wrap it.

如果你这样做,第二个是首选。更多信息更好。

于 2012-09-19T09:56:15.940 回答
1

恕我直言,这取决于您的代码与 SQL 耦合的紧密程度。

如果方法是始终(* 1)与 SQL 结合,我只需声明并重新抛出SQLException(在清理/关闭资源之后)。然后,SQL 感知的上层方法将按照他们认为合适的方式处理它(也许他们需要所有细节,也许他们不需要)。

如果将来某个时候您可以更改另一个不使用 SQL 的方法,那么我会选择第二个选项。

(1):对这个假设要格外悲观:“我认为我们不会改变”应该被解释为“我们可能会想要改变”。“我们不会改变”的意思是“无论如何,如果不打破许多其他方法,我们就无法改变”。

于 2012-09-19T10:04:06.227 回答
0

一种不同的方式是您将catch例外的方式。在第一种情况下,您可以只catch处理异常并且您知道错误是什么。在第二种情况下,您必须catch检查异常并检查代码以查看错误是什么。

于 2012-09-19T10:15:31.737 回答