正常处理数据库异常

时间:2016-10-30 08:03:33

标签: database exception design-patterns

我有一个执行程序服务,其中线程在上下文对象上运行2-3个多个进程,并在每个进程完成后将状态记录到数据库中。 当前代码在每个日志记录语句之后定义try和catch块,以便可以处理任何数据库异常,并且worker转移到下一个进程。

是否有设计模式或更优雅的方式。代码在一个不可读的函数中有多个try和catch块

代码段例如:

completePayment() {

validateAttribute1 ();
try {
logResultToDatabase() ;
//calls the entity manager to persist
}
catch (Exception e ) {
//do Nothing , continue to validateAttribute2
}
validateAttribute2 ();
try {
logResultToDatabase() ;//calls the entity manager to persist
}
catch (Exception e ) {
//do Nothing , continue to doPayment
}
doPayment();
try {
logResultToDatabase();
}
catch (Exception e ) {
//do Nothing.
}
}

1 个答案:

答案 0 :(得分:0)

首先,你永远不应该捕获异常。您应该只捕获您打算处理的异常,而不是捕获一些不相关的异常(例如,由代码中的错误引起的NullPointerException)。

你说你想处理数据库异常,所以应该捕获的异常是SQLException。

何时可以抛出SQLException?

  • 当您的代码中存在错误时,例如无效查询
  • 或无法与数据库通信时

在第一种情况下,捕获异常并不是你想要的,特别是如果你忽略异常:你最好让异常传播到调用代码,这样bug就不会被忽视,并且可以尽快修复。

在第二种情况下,要么您不在乎是否要将日志写入数据库,要么在日志失败时立即停止多步进程。

如果你想立即停止,那么你应该再次传播异常。

如果您不关心日志是否已写入,并且仍想继续,那么您所拥有的内容很好,除非它包含大量重复且不易阅读。

因此,将代码提取到方法:

public void completePayment() {
    validateAttribute1();
    logResult();

    validateAttribute2();
    logResult();

    doPayment();
    logResult();
}

private void logResult() {
    try {
        insertResultIntoDatabase();
    }
    catch (SQLException e) {
        // not thrown to avoid interrupting the payment process
        // but logged to be aware of the problems with the code or the DB
        logger.warn("Exception writing result to the database, e);
    }
}