DAO 层可以返回一个 JDBC ResultSet (Java)

Posted

技术标签:

【中文标题】DAO 层可以返回一个 JDBC ResultSet (Java)【英文标题】:DAO layer can return a JDBC ResultSet (Java) 【发布时间】:2014-07-04 08:39:21 【问题描述】:

我的 Java 项目有一个使用 Java API JDBC 的 DAO 层; JDBC 返回 ResultSets 以从数据库中获取信息。

考虑到分层的编程范式,将ResultSet对象返回业务层并将信息提取到其中是否正确?

根据层定义,业务层有责任将信息包装在领域对象(bean 等)中。但另一方面,它还没有看到 DAO 组件。

我附上这段代码来展示我的范例:

    public static Hashtable<String, TreeSet<String>> getCodesByEditorial(Vector<Integer> familiesVector) throws Exception 
        DriverManager.registerDriver((Driver) Class.forName("ianywhere.ml.jdbcodbc.IDriver").newInstance());    
        Connection con  = DriverManager.getConnection("jdbc:odbc:DSN=DBLIB");
        String sqlQuery = 
            "SELECT re.codigo, li.editorial FROM li_li li " +
            "LEFT OUTER JOIN tl_recambio re ON li.codigo = re.codigo " +
            "WHERE li.editorial IS NOT NULL AND re.familia IN (" + buildFamilies(familiesVector) + ")" ;
        PreparedStatement ps = con.prepareStatement(sqlQuery);
        ResultSet res = ps.executeQuery();

        //THIS CODE SHOULD BE INTO DAO LAYER????
        Hashtable<String, TreeSet<String>> codesHashTree = new Hashtable<String, TreeSet<String>>();  
        while (res.next()) 
            String code = res.getString("CODIGO");
            String editorial = res.getString("EDITORIAL");
            if (editorial != null)             
                TreeSet<String> bookTreeSet = codesHashTree.get(editorial);
                if (bookTreeSet == null) 
                    bookTreeSet = new TreeSet<String>();
                
                bookTreeSet.add(code);
                codesHashTree.put(editorial, bookTreeSet);
            
        
        con.close();
        return codesHashTree;
    

【问题讨论】:

从技术上讲,您可能会使用 CachedRowSet 实现(它扩展了 ResultSet 接口),但泄漏数据库抽象通常是糟糕设计的标志(尤其是当它们是需要的资源时)被关闭,就像ResultSet)。 【参考方案1】:

不,业务层不应该处理ResultSets。该层的职责是处理业务逻辑,与数据的来源(在本例中为数据库)无关。

处理这个问题的一种方法是从数据源层返回Data Transfer Objects (DTO),然后在业务层处理它们。这样,数据可以来自多种来源(数据库、平面文件、Web 服务、其他集成),并且业务层不需要更改。

【讨论】:

【参考方案2】:

我认为这是一个坏主意,因为 JDBC 类(ResultSet 就是其中之一)旨在用于从数据库中检索数据。现在,当您调用 DAO 方法时,您很可能希望获得一个域模型对象或它们的一些集合(我说的是findXXX-like 方法)。

常见的最佳实践是不要将数据源通信暴露给外层(很可能暴露给服务层)。原因:您可能曾经用键值存储、文本文件或其他东西替换数据库。如果您继续返回ResultSet,您将不得不更改很多签名。

【讨论】:

【参考方案3】:

看第一件事

如果您在DAO 层内拥有所有DB 相关逻辑,例如connection 对象、resultset 等。

那么在DAO层内部处理显然更好,并在DAO层本身关闭所有这些打开的connectionresult set

如果您将result set 返回到业务层,那么您无法在DAO 层本身中关闭resultset

这意味着您正在将您的 DAO 逻辑委托回业务层,这是打算做的

业务相关的东西。

如果关闭result set时出现异常怎么办,因为你已经返回

业务层,它在业务层产生问题。

你需要在业务层处理所有DAOexceptions

所以避免在业务层中使用resultset 或任何DB 相关的东西。

并将其纯粹用于业务逻辑。

【讨论】:

以上是关于DAO 层可以返回一个 JDBC ResultSet (Java)的主要内容,如果未能解决你的问题,请参考以下文章

如何使用JDBC实现数据访问对象层(DAO)

Java通过JDBC 进行Dao层的封装

使用普通 JDBC 在 DAO 或服务层中进行事务处理

我们可以从 DAO 层返回 json 对象吗?

编写hibernate 操作数据库的dao层简单代码

JDBC之DAO层封装思想超详解