提问人:jnemecz 提问时间:3/6/2013 最后编辑:Nathan Hughesjnemecz 更新时间:3/7/2013 访问量:12873
数据访问对象 (DAO) 中的方法应该抛出还是捕获其异常?[关闭]
Should method in data access object (DAO) throw or catch its exception? [closed]
问:
我在数据访问对象中有一个 Java 方法。这个非常简单的方法将两个整数值插入到数据库中。
public void saveHourMin(int hour, int min) throws SQLException{
psInsert.setInt(1, hour);
psInsert.setInt(2, min);
psInsert.executeUpdate();
}
当抛出 SQLException 时,此方法或一般而言,任何 DAO 方法都应该抛出异常,还是应该捕获并记录异常,然后通过返回码通知用户?对于使用 Spring 的应用程序来说,哪种方法是正确的?
答:
我会说不。捕获 SQLException,然后抛出 RuntimeException 或 if 后代。您不希望因数据访问异常而污染您的应用程序。例如,您不应该在 GUI 层中捕获 SQLExceptions。我也不会基于返回代码构建应用程序。
通过抛出 RuntimeException,您也不会强制调用方捕获它。
你不能指望调用方始终如一地检查返回代码,你最好抛出异常。
如果你抛出SQLException,那么这将是混乱的,你最终可能会得到更高的层,要么在每个方法上添加“throws Exception”,要么只是吃异常。这些替代方案都不好。
Spring 的做法是,它提供了一个异常转换器,该转换器接受原始 SQLException 并抛出 RuntimeException 的子类,该子类将原始 SQLException 作为原因,并试图提供有关错误的尽可能多的信息,包括使用供应商错误代码来决定抛出哪个特定的子类。 如果您使用任何 Spring 的 jdbcTemplates,那么您将获得异常转换功能,因此您不需要在数据访问对象中包含任何异常捕获或抛出。
如果你不想使用 Spring,你可以在 DAO 中捕获 SQLException 并抛出 RuntimeException,包括原始 SQLException 作为原因。对于大多数SQLException,您无能为力,您只想快速失败并记录异常。
评论
我将创建一个名为 DAOException 的新异常,它不是 RuntimeException,并强制该方法的用户处理此类异常,可能将枚举作为描述异常的 DAOException 的成员(可能将实际异常添加为内部异常)。
因此,抛出的异常可能如下所示:
new DAOException(DAOException.TYPE.SQLE, e)
saveHourMin 方法抛出 DAOException。
这样,如果你有各种各样的问题,它们都属于同一种例外,你不必处理不同的问题。
我之所以建议使用一般异常而不是运行时,是因为我不希望它是处理异常的可选。无论谁调用此方法,都必须意识到可能会发生此类问题并提供相关的处理(即使这意味着抛出新的 RuntimeException,上帝保佑,但现在由他们决定,这是他们的决定)。作为一般经验法则,我会避免使用 RuntimeExceptions,因为它们会使执行路径变得不清晰(“有人可能会在执行路径的某个地方捕捉到它,或者它会杀死应用程序,所以可以放手”对我来说听起来不太好)。
评论