数据访问对象 (DAO) 中的方法应该抛出还是捕获其异常? [关闭]

Posted

技术标签:

【中文标题】数据访问对象 (DAO) 中的方法应该抛出还是捕获其异常? [关闭]【英文标题】:Should method in data access object (DAO) throw or catch its exception? [closed] 【发布时间】:2013-02-20 09:55:15 【问题描述】:

我在数据访问对象中有一个 Java 方法。这个非常简单的方法将两个整数值插入到数据库中。

public void saveHourMin(int hour, int min) throws SQLException
psInsert.setInt(1, hour);
psInsert.setInt(2, min);
psInsert.executeUpdate();

这个方法,或者,一般来说,任何 DAO 方法,应该在抛出 SQLException 时抛出异常,还是应该捕获并记录异常,然后通过返回码通知用户?哪种方法适合使用 Spring 的应用程序?

【问题讨论】:

对此没有一个公认的“最佳实践”。 @MattBall - 我很确定。但我是这方面的新手,我需要了解如何解决这些情况。 实际上处理 DAO 异常最常见的做法是将它们包装在一些自定义的 DAO 异常类中。阅读 BalusC 的这篇非常好的和受欢迎的教程,其中讨论了 DAO 异常处理和其他好的实践:DAO tutorial - the data layer 【参考方案1】:

你不能指望调用者持续检查返回码,你最好抛出异常。

如果您抛出 SQLException,那将是一团糟,您最终可能会在更高层上添加“抛出异常”在每个方法上,或者只是吃异常。这两种选择都不好。

Spring 这样做的方式是提供一个异常转换器,该转换器接收原始 SQLException 并抛出包含原始 SQLException 作为原因的 RuntimeException 的子类,并尝试提供尽可能多的有关错误的信息,包括使用供应商错误代码来决定抛出哪个特定子类。 如果您使用 Spring 的任何 jdbcTemplates,那么您将获得异常转换功能,因此您不需要在数据访问对象中包含任何异常捕获或抛出。

如果不想使用 Spring,可以在 DAO 中捕获 SQLException 并抛出 RuntimeException,包括原来的 SQLException 作为原因。对于大多数 SQLException,您无能为力,您只想快速失败并记录异常。

【讨论】:

我使用 Spring。您能否提供更多信息如何在 Spring Framework 中解决此问题? @user1315357 从这里开始:static.springsource.org/spring/docs/3.2.x/…。使用 jdbc 模板,您将可以访问异常翻译。 static.springsource.org/spring/docs/3.2.x/… @user1315357 另请参阅本教程,了解使用 spring jdbc 可以为您节省多少代码:dzone.com/tutorials/java/spring/spring-jdbc-tutorial-1.html。谷歌搜索“spring jdbc tutorial”带来了很多东西。【参考方案2】:

我会说不。捕获 SQLException,然后抛出 RuntimeException 或一个 if 后代。您不想让数据访问异常污染您的应用程序。例如,您不应该在 GUI 层中捕获 SQLExceptions。我也不会基于返回码构建应用程序。

通过抛出 RuntimeException,您也不会强制调用者捕获它。

【讨论】:

【参考方案3】:

我将创建一个名为 DAOException 的新异常,它不是 RuntimeException,并强制该方法的用户处理此类异常,并可能将枚举作为描述异常的 DAOException 的成员(可能添加实际异常内部异常)。

所以抛出的异常可能如下所示:

new DAOException(DAOException.TYPE.SQLE, e)

saveHourMin 方法抛出 DAOException。

这样如果遇到各种问题,都属于同一种异常,不用处理不同的异常。

我建议使用一般异常而不是运行时的原因是因为我不希望它是可选的来处理异常。调用此方法的人必须意识到可能会发生此类问题并提供相关处理(即使这意味着抛出新的 RuntimeException,上帝保佑,但现在由他们决定,这是他们的决定)。作为一般的经验法则,我会避免使用 RuntimeExceptions,因为它们使执行路径不清楚(“有人可能会在执行路径的某个地方捕捉到它,否则它会杀死应用程序,所以可以放手”听起来不对我好)。

【讨论】:

以上是关于数据访问对象 (DAO) 中的方法应该抛出还是捕获其异常? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

sping揭秘18使用spring访问数据

MVC 中的单个 DAO 还是多个 DAO?

在 Ruby 上设计 DAO

数据访问对象 (DAO) 是不是应该委托给其他 DAO 以提高可读性?

JavaEE6 DAO:应该是@Stateless 还是@ApplicationScoped?

Azure 函数应该记录错误还是抛出异常?