【问题标题】: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的块可以发生呢?

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

【问题讨论】:

    标签: java dao behavior api-design


    【解决方案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】:
    1. 空。但是方法getCustomer() 应该返回客户。如果它返回字符串,它可能应该被称为getCustomerName()getCustomerId()
    2. 空列表
    3. 抛出异常。可能用应用层异常包装它。

    【讨论】:

    • +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 处理。无论如何感谢您的建议:-)
    猜你喜欢
    • 1970-01-01
    • 2013-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-20
    • 1970-01-01
    • 2021-02-15
    相关资源
    最近更新 更多