【问题标题】:Streaming DAO Results in Java (Design Pattern)在 Java 中流式处理 DAO 结果(设计模式)
【发布时间】:2011-01-14 10:25:09
【问题描述】:

鉴于以下情况:

  • DAO 从表中查询所有行并将它们映射到域对象列表(纯 JDBC
  • 处理由 DAO 生成的列表并将某些列表元素格式化为文件的服务。

这里的问题是所有 DAO 结果都保存在内存中,随着表的增长,这变得很危险。

问题: 是否存在以流方式从 DAO 读取对象的模式,服务一次只处理一个元素,将其写入文件输出流,然后请求下一个元素从结果集中?使用ResultSet 作为 DAO 的返回类型通常是个好主意吗?

【问题讨论】:

    标签: java design-patterns jdbc export dao


    【解决方案1】:

    即使您不应该公开结果集,默认情况下您仍然不会获得流语义。为此,您需要执行以下操作:

    stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
                  java.sql.ResultSet.CONCUR_READ_ONLY);
    stmt.setFetchSize(Integer.MIN_VALUE);
    

    您应该将它封装在您的 DAO 中,您可以返回一个自定义迭代器来处理结果。

    请参阅mysql reference,了解有关流结果的主题。

    【讨论】:

    • 谢谢!我有同样的感觉,公开 ResultSets 不是一个好主意。迭代器是一个很好的提示!我仍然想知道是否值得为将(一点)BL 从数据库查询逻辑中分离出来而付出努力。我想一般人只是把它混在一个班级里?
    • 一般BL和DB逻辑是不交织的。从您的 DAO 返回自定义迭代器将是最简单和最干净的解决方案。
    【解决方案2】:

    最好的方法是进行分页查询,您可以获取总行数,然后选择页面大小并使用您的数据库工具(oracle 的 rowid)来获取页面,直到您拥有所有行,或者您可以只是继续查询,直到没有结果为止。

    【讨论】:

    • DAO 界面会是什么样子呢?请记住,我想保持业务逻辑(服务)和查询逻辑(DAO)之间的分离。
    【解决方案3】:

    所以你只处理给定的行一次?您可以在数据库中将该行标记为已处理,并且只选择未处理的行。或者,您可以将已处理的行移动到不同的表中。

    【讨论】:

    • 您的建议意味着每行至少有一次更新。当你有例如这听起来不是很高效大约 10 万或百万行。
    • 好点。此页面上的其他选项看起来更可取。
    【解决方案4】:

    从不从 DAO 返回 ResultSet,将数据逻辑封装在数据类中。

    我可能也永远不会编写返回整个表的 DAO 方法,这似乎有点太笼统了。相反,我可能会编写一个名为dumpToFile(File f) 的DAO 方法,它在内部完成了整个工作。这样,DAO 可以一次读取一条记录并将它们写入文件。

    【讨论】:

    • 假设服务正在进行某些验证,由于业务规则而跳过一些记录并对其进行格式化。当应用关注点分离的概念时,这些不是在 DAO 中要做的事情。这就是我问的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-14
    • 2011-04-14
    • 1970-01-01
    • 2011-05-31
    • 2013-07-12
    • 1970-01-01
    • 2015-01-26
    相关资源
    最近更新 更多