我已经看到并使用过许多通常以 CRUD 方法开始的基于 JDBC 的旧 DAO 代码。我的问题具体涉及检索方法或“查找器”。通常我发现 DAO 以两种方法开始:
- 查找并返回所有
- 根据唯一标识符检索特定实例
通常情况下,这两个发现者是不够的。我通常最终会看到一个 DAO 类被反复修改以添加如下查找器方法:
- 查找并返回所有 {condition}
发生的情况是,当需要支持新的 {conditions} 或修改现有方法以添加新参数作为标志以修改方法内的 SQL 查询以支持其他条件时,会添加更多方法。
这是一种丑陋的方法,违反了开闭原则。每当需要支持某些新的检索条件时,看到 DAO 类不断修改一直是我的烦恼。对这个问题的研究经常将我指向存储库模式和封装检索条件作为 Specifications或查询对象,然后将它们传递给查找器方法。但这似乎只有在您拥有整个数据集的内存集合或者您使用某种 ORM(我正在使用较旧的 JDBC 代码)时才可行
我考虑过一种解决方案,它延迟加载 DAO 管理的整个数据集作为内存中的集合,然后使用规范模式作为检索查询。然后我在集合上实现某种观察者,它只在创建、更新或删除方法被调用时更新数据库。但显然性能和可伸缩性受到严重影响。
对此有什么想法吗?
感谢您到目前为止的回复。我确实有一个想法——您对使用命令/策略模式来封装数据访问请求有何看法?每个单独的具体命令都可以代表一种特定类型的访问,并且可以传递给调用程序。我最终会得到许多 Concrete 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();
最佳答案
我们已经将 iBatis 用于我们的数据层 ORM,并且已经能够通过传递一个包含您可能希望用作参数的各种字段的参数对象来实现您在一个查询中提出的建议。
然后在您的 WHERE 子句中,您可以将每个字段指定为条件子句,但前提是它填充在参数对象中。如果参数 obj 中只有一个字段不为空,那么它将是唯一一个将用于过滤结果的字段。
因此,如果您需要向参数添加字段,您只需更改 SQL 和 paramObj。然后,您可以有 2 个方法返回 ALL 或基于传递的参数组合的子集,或者至少这种方法会减少所需的查询数量。
例如类似...的东西
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>
关于java - DAO 模式和开闭原则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5026186/