我已经看过并使用过许多基于JDBC的旧代码,这些代码通常都是以CRUD方法开始的。我的问题特别涉及检索方法或“发现者”。通常我发现DAO开始时有两种方法:
这两个发现者往往不够。我通常最终会看到一个DAO类被反复修改以添加如下所示的finder方法:
当需要支持新的{conditions}或修改现有方法以添加新参数作为标志以修改方法内的SQL查询以支持其他条件时,会添加更多方法。
这是一种丑陋的做法,违反了开放封闭原则。每当需要支持一些新的检索条件时,看到DAO类不断修改,这一直是我的一个难得。对这个问题的研究经常指向Repository Pattern和封装条件,以便将检索作为Specifications或Query对象传递给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();
答案 0 :(得分:4)
我们已经将iBatis用于我们的数据层ORM,并且能够通过传递一个参数对象来实现您在一个查询中提出的建议,该参数对象包含您可能希望用作参数的各个字段。
然后在WHERE子句中,您可以将每个字段指定为条件子句,但前提是它填充在参数对象中。如果param obj中只有一个字段不为null,则它是唯一一个用于过滤结果的字段。
因此,如果需要向参数添加字段,只需更改SQL和paramObj。然后,您可以根据传递的参数组合返回2个返回ALL或子集的方法,或者至少这种方法会减少所需查询的数量。
e.g。有些东西......
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>
答案 1 :(得分:0)
为什么不创建通用的查找器API,而不是为每个可能的条件创建特定的查找器方法? 这可以采用具有内部枚举的DAO来表示字段的形式,以及采用DAO的内部类的实例列表的方法,其中字段表示要过滤的DAO的哪个字段,要对其应用什么过滤器,什么条件(AND,OR等)。
设置这项工作有点费用,对于小型项目来说可能有些过分,但这肯定是可行的。 ORM框架通常具有内置的类似功能,因此您可能需要考虑采用其中之一(或者至少在设计自己的解决方案时,如何实现它以便改进您的遗留应用程序)。