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

Should method in data access object (DAO) throw or catch its exception? [closed]

提问人:jnemecz 提问时间:3/6/2013 最后编辑:Nathan Hughesjnemecz 更新时间:3/7/2013 访问量:12873

问:

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

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

当抛出 SQLException 时,此方法或一般而言,任何 DAO 方法都应该抛出异常,还是应该捕获并记录异常,然后通过返回码通知用户?对于使用 Spring 的应用程序来说,哪种方法是正确的?

Java Spring Jakarta-EE 架构 DAO

评论

5赞 Matt Ball 3/6/2013
对此,没有人商定的“最佳实践”。
0赞 jnemecz 3/6/2013
@MattBall - 我确信这一点。但我是这方面的新手,我需要了解如何解决这些情况。
0赞 informatik01 4/25/2013
实际上,处理 DAO 异常的最常见做法是将它们包装在一些自定义 DAO 异常类中。阅读 BalusC 的这个非常好且流行的教程,其中讨论了 DAO 异常处理和其他良好实践: DAO 教程 - 数据层

答:

1赞 LuckyLuke 3/6/2013 #1

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

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

6赞 Nathan Hughes 3/6/2013 #2

你不能指望调用方始终如一地检查返回代码,你最好抛出异常。

如果你抛出SQLException,那么这将是混乱的,你最终可能会得到更高的层,要么在每个方法上添加“throws Exception”,要么只是吃异常。这些替代方案都不好。

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

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

评论

0赞 jnemecz 3/6/2013
我用Spring。您能为我提供更多信息如何在 Spring Framework 中解决这个问题吗?
2赞 Nathan Hughes 3/6/2013
@user1315357从这里开始:static.springsource.org/spring/docs/3.2.x/...。使用 JDBC 模板,您将可以访问异常转换。static.springsource.org/spring/docs/3.2.x/......
0赞 Nathan Hughes 3/6/2013
@user1315357还可以查看本教程,了解使用 Spring JDBC 可以为您节省多少代码:dzone.com/tutorials/java/spring/spring-jdbc-tutorial-1.html。谷歌搜索“Spring JDBC Tutorial”会带来很多东西。
1赞 TheZuck 3/6/2013 #3

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

因此,抛出的异常可能如下所示:

new DAOException(DAOException.TYPE.SQLE, e)

saveHourMin 方法抛出 DAOException。

这样,如果你有各种各样的问题,它们都属于同一种例外,你不必处理不同的问题。

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