在项目开发过程中,DAO层的设计是必经的一个步骤。在CRUD中,使用最多的可能是Query操作了。
DAO层的实现即可以使用原生态的JDBC,也可以使用各种ORM框架。在此,仅仅是想探讨下各种技术针对动态条件查询的设计方式。
技术方案:纯JDBC
1 每一个方法参数对应一个sql条件项目 方法签名:queryOrdersByClintAndTradeDate(String clientID, Date tradeDate);
优点:方法意图明确,参数清晰。
缺点:扩展性差。如果增加查询条件,修改原方法会改变原查询逻辑,进行方法重载会增加DAO类的复杂度。
特别是在查询逻辑多变的业务背景下,只是因为不同的查询参数进行方法重载,方法数据会直线上升,显得DAO类太过臃肿。
2 使用集合对象封装简单的不定数量的查询语句
采用Object数组封装N个查询条件
方法签名:queryOrders(String sql, Object[] params);
方法说明:方法内部使用sql定义查询结构,params存储参数值。
优点:初步解决了不定查询条件的查询模式。方法接口比较稳定,不会因为查询条件变化调整结构。
缺点:通过方法定义无法明确查询字段。
采用Map封装N个类似的查询条件
方法签名:queryOrders(String sql, Map params);
方法说明:sql定义部分查询sql,params存储条件字段和参数值
优点:支持简单的自定义sql组装。方法接口比较稳定。
缺点:通过方法定义无法一目了然的明确查询结构。另外,参数代码和参数值之间只能存在特定的比较关系,比如条件A=100(这种比较关系只能在方法内部确定一种)。如果需要根据params动态组装sql,那么各个条件项之间也只能在方法内部支持一种固定的拼接模式(例如条件A = 100 AND 条件B = 200 AND 条件C = 300)。
3 把查询条件项封装为查询条件对象
定义对象:Parameter
/**
*
* @param field 数据库字段名
* @param operator 数据库操作符 =、>=、
* @param value 参数值 Object
*/
public Parameter(String field,String operator, Object value)
方法签名:queryOrders(String baseSql, List params)
方法说明:sql定义基本sql结构。params为查询条件对象数组。
方法使用示例:
Parameter A = new Parameter("A" ,"like","A%");
Parameter B = new Parameter("B" ,"">="",java.sql.Date.valueOf("2013-11-04"));
String sql = "select * from table";
List paramList = new List();
paramList.add(A);
paramList.add(B);
queryOrders(sql,paramList);
优点:支持自定义的动态查询条件。
缺点:同上。
综上所述,我个人是支持第三种设计方式。这种定义条件对象的设计方式,可以继续深化扩展,把sql组装的各个部分都采用对象化的方式来定义,从而支持灵活的查询结构。
流行框架Hibernate中就提供了一套良好定义的类支持灵活的DAO处理。hibernate中的具体实现就不在此章节赘述。
本文章只是包含了DAO设计中的一个小篇章,持久化是一个大主题,通过分析原理再结合流行框架的具体设计,希望可以提升自己设计和思考能力。