锁定老帖子 主题:5种DAO查询方法的签名方式,哪个更好?
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-01-03
DAO层除了CRUD的数据操作外,另一个重要的操作就是根据查询条件执行数据查询,不同的ORM框架都允许用户动态绑定参数确定查询条件。查询条件项的数目往往是不固定的,如既可能要求以userName为条件查询User,也可能要求以userName+status等组合条件查询User。条件项数目的不定性给查询接口方法的设计造成为一定的困难,实体DAO定义带参的查询方法时,一般有5种方式,下面分别对这些方法进行介绍。 方式1:每一个条件项参数对应一个入参 查询方法中为每一个查询条件项定义一个对应的入参,如: List findOrder(String hql,Date startTime,Date endTime,int deptId) 这种方法签名含义清晰,可读性强,内部的逻辑处理简单,但接口稳定性差。 假如这个findOrder()方法需要添加一个userName的条件,有两种重构的方式:第一,调整方法的签名,新增一个String userName入参,这种重构被认为是不健康的重构,因为它违反软件设计中经典的“开-闭原则”,此外如果条件项个数很多,方法签名将显得过于拖沓;第二,在DAO类中新增一个重载查询方法,如果查询条件项的组合数过多,DAO类的方法数目将直线上升,整个实体DAO类将显得臃肿笨重。 方式2:使用数组传递条件项参数 通过数组的方式传递查询条件项参数,由于参数类型的不一致性,要求数组类型采用Object[]: List findOrder(String hql,Object[] params) 这种方法接口可以应付查询条件项参数组合的多样性并保持接口的稳定性,开发者必须在方法内部从数组中获取参数再传递给查询引擎。缺点是方法的可读性不强,调用者往往需要通过查看接口对应的Javadoc才能正确使用。此外,在JDK 5.0以下的版本中,因为没有自动拆/解包的语法特性,调用前必须对基本类型的参数使用封装类封装,有时在方法内部还需要进行相反的过程,在使用上较为不便。不过由于Spring为支持的ORM框架都提供了类似的查询接口(如HibernateTemplate#find(String queryString, Object[] values)),所以DAO方法内部的处理相对还是比较简单的。 方式3:使用JDK 5.0的不定参数 如果在JDK 5.0中,则可以采用不定参数进行方法签名,这种方式在逻辑上和方式2并无多大的区别: List findOrder(String hql,Object... params) 方式4:将查询条件项参数封装成对象 为了提高方法1中方法签名简洁性,增强方法2、3中方法签名的可读性,方式4提出将查询条件项参数封装成一个对象的思路,查询方法使用查询条件对象传递查询条件: List<Order> findOrder(String hql,OrderQueryParam param) OrderQueryParam查询条件对象封装了hql查询语句可能会用到的条件项参数,在查询方法内部,开发者必须判断查询条件对象的属性并正确绑定条件项参数。由于需要为条件项参数定义一个类,因此会造成类数目的膨胀,有时甚至一个实体DAO需要对应多个查询条件参数类。另外,当需要添加一个新的条件项参数时,条件封装类还需要进行相应调整。 方式5:使用Map传递条件项参数 另一种被广泛使用的方法是采用Map传递条件项参数,键为参数名,值为参数值: List<Order> findOrder(String hql,Map params) 使用这种方式,接口方法签名可以在条件项发生变化的情况下保持稳定,同时通过键指定条件项参数名在一定程度上解决了接口的健壮性(当调用者指定错误参数名时容易得到错误报警)。但和方法2、3一样调用者必须通过接口Javadoc才能明白不同条件项要以什么名称进行设置。 注:以上5个查询方法签名的总结摘自于《精通Spring 2.x--企业应用开发详解》 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-01-03
我们一般是写了一个分页查询的方法:
List pagedQuery(Page page, Where where); where条件是一个条件树,可以任意进行组合完成复杂的条件查询。 |
|
返回顶楼 | |
发表时间:2008-01-03
Where where = Where.rootWhere("prop",Where.EQ,object); |
|
返回顶楼 | |
发表时间:2008-01-03
tianhen 写道 Where where = Where.rootWhere("prop",Where.EQ,object); 这种方式挺有创意的,也相当灵活,相当不错! |
|
返回顶楼 | |
发表时间:2008-01-04
没明白啊,能否给个例子?
|
|
返回顶楼 | |
发表时间:2008-01-08
stamen 写道 tianhen 写道 Where where = Where.rootWhere("prop",Where.EQ,object); 这种方式挺有创意的,也相当灵活,相当不错! Hibernate似乎有类似的组件吧。。。当然了不用Hibernate就是另外一码事。。。 |
|
返回顶楼 | |
发表时间:2008-01-08
Criteria更好.
and( eq("thisDN",750), gt("size",5) or( eq("otherDN",110), like("name","%Rason%") ) ) |
|
返回顶楼 | |
发表时间:2008-01-10
EXvision 写道 stamen 写道 tianhen 写道 Where where = Where.rootWhere("prop",Where.EQ,object); 这种方式挺有创意的,也相当灵活,相当不错! Hibernate似乎有类似的组件吧。。。当然了不用Hibernate就是另外一码事。。。 他的灵感来源于hibernate的Criteria |
|
返回顶楼 | |
发表时间:2008-01-10
我觉得上面的5种方式都不够优雅
不过也没发现有什么好的方式~~~ 除非自己实现一套类似与hibernate的Criteria |
|
返回顶楼 | |
发表时间:2008-01-10
ibatis用的就是方法4 查询条件当对象传入 这样挺好的
|
|
返回顶楼 | |