正确处理返回数据[关闭]

Posted

技术标签:

【中文标题】正确处理返回数据[关闭]【英文标题】:Correct handling of return data [closed] 【发布时间】:2011-06-22 19:13:40 【问题描述】:

我有一个关于正确处理我正在为一个项目编写的 DAO 库的返回的问题。这个库可能会被其他人使用,我想正确地做到这一点。我应该如何处理我的 DAO 函数的返回语句?

示例 1 我有 getCustomer 的函数,它应该返回字符串。如果查询没有返回任何结果,我应该返回 null、空字符串还是抛出某种异常?

示例 2 我有一个函数getCutomerList,它返回一个ArrayList 类型的值。如果查询没有返回任何结果,我应该返回 null、空的 ArrayList 还是抛出一些异常?

示例 3 检测到一些SQL异常,我该怎么办,抛出异常还是try..catch的块可以发生呢?

在我的案例中应用的“良好”做法或“最佳”做法是什么?

【问题讨论】:

【参考方案1】:

看来您的库正在执行类似数据库的调用。如果是这种情况,那么我将完全按照JPA 2 specification 的方式执行。

我的意思是,查看JPA API 中的find() 方法并准确返回他们在那里所做的事情。

    /**
     * Find by primary key.
     * @param entityClass
     * @param primaryKey
     * @return the found entity instance or null
     *    if the entity does not exist
     * @throws IllegalStateException if this EntityManager has been closed.
     * @throws IllegalArgumentException if the first argument does
     *    not denote an entity type or the second
     *    argument is not a valid type for that
     *    entity's primary key
     */
    public <T> T find(Class<T> entityClass, Object primaryKey);

你在这里看到find,我认为它类似于你的getCustomer()方法,如果没有找到它将返回null,如果参数无效则只抛出IllegalArgumentException

如果find() 方法与getCustomer() 的方法不接近,您应该实现与getSingleResult() 相同的行为:

    /**
     * Execute a SELECT query that returns a single result.
     * @return the result
     * @throws EntityNotFoundException if there is no result
     * @throws NonUniqueResultException if more than one result
     * @throws IllegalStateException if called for a Java 
     *    Persistence query language UPDATE or DELETE statement
     */
    public Object getSingleResult();

如果没有找到结果将抛出EntityNotFoundException,如果找到多个实例则抛出NonUniqueResultException,如果SQL 错误则抛出IllegalStateException

你必须决定哪种行为最适合你。

getResultList() 也是如此:

/**
 * Execute a SELECT query and return the query results
 * as a List.
 * @return a list of the results
 * @throws IllegalStateException if called for a Java 
 *    Persistence query language UPDATE or DELETE statement
 */   
public List getResultList();

getResultList() 将返回 null 如果没有找到,并且只在 SQL 非法时抛出异常。

通过遵循这种行为,您将保持一致,并且您的用户会感觉了解图书馆的情况。


另一种行为是返回一个空集合而不是null。这就是Google Guava 实现其 API 的方式,这确实是首选原因。但是,我喜欢一致性,并且仍然认为您应该尽可能接近standard 来实现该库。


资源

Joshua Bloch made a video explaining how to design a good API and why it matters.

【讨论】:

请注意,javadoc 与 jpa 2 api 并不完全相同,但行为相似 好吧,在没有找到元素的情况下抛出特殊异常似乎很有说服力,并且杀死参数 :P 是用户对 api 感到满意。非常感谢您的帮助:) 另请阅读我给您的资源链接,如果您愿意,请记住将答案标记为已接受 100% 被接受 ;) 很好的答案。 一个关于错字的快速说明:对于 getSingleResult,您的解释列出了 EntityNotFoundException 两次。第二个应该是 NonUniqueResultException。仍然,一个惊人的答案。 +1。【参考方案2】:
    空。但是方法getCustomer() 应该返回客户。如果它返回字符串,它可能应该被称为getCustomerName()getCustomerId() 空列表 抛出异常。可能用应用层异常包装它。

【讨论】:

+1 表示getCustomer 应该返回一个对象。否则null 可能会模棱两可。客户名称是空的,还是找不到客户? 好的,我的函数更多的是 getCustomerName 然后是 getCustomer,显然我会返回 Customer 而不是 String ;) 但无论如何感谢指出那个失误【参考方案3】:

示例 1:由于没有检索到任何内容,因此应返回 null。或者,Null-Object 模式 可以作为一种选择。

示例 2:首选 empty ArrayList 而不是 null。参见“Effective Java”第 43 条:返回空数组或集合,而不是空值

示例 3:将 SQLException 转换为更高的 Exception 并抛出它。参见“Effective Java”第 61 条:抛出适合抽象的异常

【讨论】:

使用 Null-Object 模式的有趣方法,需要更仔细地了解这一点。感谢您指出对 Effective Java 的引用【参考方案4】:

既然它是你的 API,任何方法都是好的,只要你保持一致并确保它被正确记录。

对于 1 和 2: 但请注意,返回 null 将强制客户端代码继续执行如下检查:

result = yourAPICall();
if(result != null)
   // do something

这就是为什么我更喜欢返回空对象或集合

对于 3: 这将取决于您的 API 设计。但首先,永远不要在调用堆栈中抛出低级异常。您应该将它们包装在为您的 API 设计的自定义异常类中,以便您的客户端代码只需要捕获您的 API 异常,而不是各种较低级别的异常(SQLException、IOException 等)

其次,您必须首先确定抛出异常是否有任何好处。抛出异常允许客户端代码自定义它希望如何处理其 API 依赖项遇到的问题。但是抛出它也会阻止作为 API 设计者的您设计内部突发事件,从而让您的代码可能从问题中恢复(使您的 API 不那么健壮)

【讨论】:

对于 3,我创建了自定义异常,例如 ElemenetNotFoundException,以及一些与连接相关的异常,正在由 api 处理。无论如何感谢您的建议:-)

以上是关于正确处理返回数据[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Mysql 行计数为连接表返回不正确的值[关闭]

PHP CURL 没有正确处理编码的返回数据

jdbc数据库连接在方法中,而且要返回statement 或resultset 在方法里关闭连接会怎么样?要怎么处理?

为啥数据库或语言平台在执行查询时不返回强类型类? [关闭]

android 多语言--后台返回数据处理

为啥函数没有返回值? [关闭]