DAO模式和开放原则

10 java finder dao design-patterns open-closed-principle

我已经看过并使用过很多基于JDBC的旧代码,这些代码通常都是以CRUD方法开始的.我的问题特别涉及检索方法或"发现者".通常我发现DAO开始时有两种方法:

  • 找到并返回ALL
  • 基于唯一标识符检索特定实例

通常情况下,这两个发现者是不够的.我通常最终会看到一个DAO类被反复修改以添加如下所示的finder方法:

  • 找到并返回所有{condition}

当需要支持新的{conditions}或修改现有方法以添加新参数作为标志来修改方法内的SQL查询以支持其他条件时,会发生更多方法.

这是一种丑陋的方法,违反了开放封闭原则.每当需要支持一些新的检索条件时,看到DAO类不断修改,这一直是我的一个难得.对这个问题的研究经常指向Repository Pattern和封装条件,以便将其作为规范或查询对象进行检索,然后将它们传递给finder方法.但是,如果你有一个整个数据集的内存集合,或者你正在使用某种ORM(我正在使用旧的JDBC代码),这似乎是可行的.

我已经考虑过延迟加载整个数据集的解决方案,DAO作为内存中的集合进行管理,然后使用规范模式作为检索查询.然后我在集合上实现某种观察器,它只是在调用创建,更新或删除方法时更新数据库.但显然性能和可扩展性受到严重影响.

有什么想法吗?


感谢您到目前为止的回复.我有一个想法 - 您对使用命令/策略模式封装数据访问请求有何看法?每个单独的Concrete Command都可以表示特定类型的访问,并且可以传递给Invoker.我最终得到了许多具体的Command Command类,但是每一个都只关注一种访问,应该是非常可测试和隔离的.

    public abstract class Command<R>{
       public <R> execute();
       public void setArguments(CommandArguments args){
          //store arguments  
       }
    }

    //map based structure for storing and returning arguments
    public class CommandArguments{
         public String getAsString(String key);
         public String getAsInt(String key);
         //... others
    }

    //In some business class...
    Command command = CommandFactory.create("SearchByName");
    CommandArguments args = new CommandArguments();
    args.setValue("name", name);
    // others
    command.setArguments(args);
    List<Customer> list  = command.execute();
Run Code Online (Sandbox Code Playgroud)

Mad*_*urf 4

我们已将 iBatis 用于数据层 ORM,并且能够通过传递一个参数对象以及您可能希望用作参数的各种字段来实现您在一个查询中提出的建议。

然后,在 WHERE 子句中,您可以将每个字段指定为条件子句,但前提是该字段填充在参数对象中。如果参数 obj 中只有一个字段不为空,那么它是唯一一个用于过滤结果的字段。

因此,如果您需要向参数添加字段,您只需更改 SQL 和 paramObj。然后,您可以有 2 个方法根据传递的参数组合返回全部或子集,或者至少这种方法会减少所需的查询数量。

例如,类似于...的东西

SELECT * FROM MY_TABLE
WHERE FIELD_ZERO = paramObj.field0
<isNotNull property="paramObj.field1">AND FIELD_ONE = paramObj.field1</isNotNull>
<isNotNull property="paramObj.field2">AND FIELD_TWO = paramObj.field2</isNotNull>
<isNotNull property="paramObj.field3">AND FIELD_THREE = paramObj.field3</isNotNull>
Run Code Online (Sandbox Code Playgroud)