论坛首页 入门技术论坛

数据库动态查询最佳实现

浏览 12259 次
该帖已经被评为新手帖
作者 正文
   发表时间:2009-03-24   最后修改:2009-04-09

上次发表过这样的介绍,可能是我介绍的不够准确,太多人都没有搞明白(挺郁闷,当然也请大家将文章能够看的仔细点,主要是提供针对hibernate查询不足的弥补(当然这种做法并不局限于hibernate,事实上是针对所有涉及数据库查询的一个非常好的解决办法,这里且拿hibernate说事),简单的查询可以不考虑如:User user=(User)this.getHibernateTemplate().get(User.class,id); this.getHibernateTemplate().find("from User where enable=?","") ,这些大家其实都差不多,还有就是hibernate的条件查询Criteria很多人都会就不特别说了)。

还是开门见山,本文所要介绍的是针对数据库查询(当然要是ldap什么的基于查询指令的都适用),其目的在于将sql跟代码进行分离,同时能够保持sql或hql语句的

结构完整性(写sql的步骤一般是:在数据库客户端整理好sql并排版好放到代码中用stringbuffer拼起来,要是修改就痛苦了,还得调试代码得到整个语句),请好好看上面红色字的内容,平时是不是这样做的?如果是你就接着看下面的内容,对你帮助很大!

我们有很多时候数据库查询是由多个条件组合而成,但究竟是哪个条件是不确定的

展示一下效果:

 提示一下,本功能支持hql查询如(对于hql优点主要体现在查询条件不固定时,hql写法非常优雅):

 <sql-query name="hr_searchOrganInfo">
  <![CDATA[
  from HrOrganInfo
  where 1=1
  #[and createDate>=? and createDate<=?]
  #[and ORGAN_NO like ?]
  #[and ORGAN_NAME like ?]
  #[and IS_ACTIVE=?]
 ]]>
 </sql-query>


 

本功能最大的优点在于动态查询条件时hql或sql的写法非常的优雅,结构完整!
 调用方法:

   sql语句可以是

   select * from t where t.name=:name and t.createDate>:createDate 不一定是?号,以解除使用者需要记住参数顺序

的烦恼。

1、分页调用

    通过反调映射到对象

    PaginationModel findPageByJdbc(final String sqlOrNamedSql,
   final String[] paramsNamed, final Object[] paramsObj,
   final PaginationModel paginationModel,
   final RowCallbackHandler rowCallbackHandler);

   

   直接返回数据库结果结合,不映射对象

   PaginationModel findPageByJdbc(final String sqlOrNamedSql,
   final String[] paramsNamed, final Object[] paramsObj,
   final PaginationModel paginationModel);

 

 

   直接转VO式调用

    PaginationModel findPageByJdbc(final String sqlOrNamedSql,
   final String[] paramsNamed, final Object[] paramsObj,
   final PaginationModel paginationModel, final Class voClass);

2、非分页反调方式

   直接数据库数据集合返回

   List findByJdbcQuery(final String sqlOrNamedSql,
   final String[] paramsNamed, final Object[] paramsValue);

 通过反调映射到对象

   List findByJdbcQuery(final String sqlOrNamedSql,
   final String[] paramsNamed, final Object[] paramsValue,
   final RowCallbackHandler rowCallHandler)

  直接转VO对象调用

   List findByJdbcQuery(final String sqlOrNamedSql,
   final String[] paramsNamed, final Object[] paramsValue,
   final Class voClass)

 hql的调用差不多:findByhql 或findPageByhql,参数当然就没有voClass和RowCallbackHandler了,因为hql返回的就是对象集合!

 

 

 工作机理很简单,就是通过判断参数是否为null(结合sql特性如is null)对sql语句进行重新整理,后台提供了convertSqlParams功能将特定值转为null

this.findPageByJdbc("hr_getOrganInfoByNo", null,new Object[] { organNO,this.convertSqlParams(status,"-1")}, pageModel,OrganInfoVO.class);

提供java反射器直接映射成VO,也提供了RowCallbackHandler通过反调方式生成VO,当然voClass和RowCallbackHandler都为null,就直接返回数组集合!

 

 

 

  • 大小: 69.1 KB
   发表时间:2009-03-24  
我以前也觉得sql很丑陋,但是后来发现它后面还有一套优雅的代数学,反而就觉得sql外面的那些东西很丑陋了……
0 请登录后投票
   发表时间:2009-03-24   最后修改:2009-04-09
night_stalker 写道
我以前也觉得sql很丑陋,但是后来发现它后面还有一套优雅的代数学,反而就觉得sql外面的那些东西很丑陋了……

不想多评价,程序的优雅性和可读性以及提供给开发人员的简单性都很重要,我们的团队现在都在这么用,代码量大大减少,sql语句维护也简单方便,要修改直接从xml文件中抠出来改改再放进去,从他们的感受来说已经极其依赖这样的东西了,因为实在是简单易用和直观!
   而且在xml中sql的结构仍然是非常清晰,这对后期维护是非常重要的!
0 请登录后投票
   发表时间:2009-03-27  
现在人真怪异了,难道大家做开发数据库不是用的最多嘛?做系统不就是为了查询统计嘛?查询难道就不涉及到sql或hql嘛?写sql和hql难道你们就习惯用
if(查询条件不为空或什么)
  queryStr.append()吗?
我真服了,如此常用的好东西没有人关心,数据库部分在开发中占多大比重不清楚?!
就整天胡扯一些飘忽的技术,有人说面向对象根本不需要写sql,hql多表时性能是低劣的,有些功能hql是没有办法做到的,所以简单的可以用hql,复杂的需要用sql,当然不管是sql还是hql动态参数时if() append()是极其丑陋的,sql或hql写在代码中也是极其痛苦的!
0 请登录后投票
   发表时间:2009-03-27   最后修改:2009-03-27
哈哈,我在站内查了一下,关于动态查询的,如介绍DynamicQueryTool什么的(被评为精华贴),说实话我的这种做法非常优雅,一点都不夸张!
0 请登录后投票
   发表时间:2009-03-27  
MakeLove 写道
黄婆的厉害

哈哈,实事求是而已!再就是想把这种思想推荐给大家的心情比较急切,希望大家能够用上正真好的东西和好的方法,更希望大家能够真正的看文章,更要看三种写法的特点,有益就发言,有更好的想法可以提出来!
0 请登录后投票
   发表时间:2009-03-27  
请问动态表名如何实现?
0 请登录后投票
   发表时间:2009-03-27  
longrui 写道
请问动态表名如何实现?

这要看你怎么动态表法了,#[]支持嵌套如#[#[]]其实就相当于if( if()),通过这个其实是可以做到动态表的,但是不建议这么做,为什么不把这种问题作为服务逻辑呢?多写几个sql,在service中判断不同类型选择调用不同sql不就行了,动态也得把握一个度,我的目标是保持sql的结构,将sql从代码中脱离,所以我建议你写多个sql,或则针对这类极其特殊的问题用特殊办法对待(我们要为解决98%的问题,2%的特殊情况完全可以自行处理,解决了98%何必又那么苛刻要100%呢,98%还不比0%好嘛?)
0 请登录后投票
   发表时间:2009-03-27  
大家在这篇2年前的帖子中讨论过各种类似做法:
http://www.iteye.com/topic/58834
你提出的想法是在约定大于配置上更进一步,少去了一些tag,如果更进一步,连#[]都可以省略,可以and开头,换行结尾作为匹配:
from HrOrganInfo where 1=1
and createDate>= ? and createDate<= ?
and ORGAN_NO like ?
and ORGAN_NAME like ?
and IS_ACTIVE = ?
0 请登录后投票
   发表时间:2009-03-27   最后修改:2009-03-27
QuakeWang 写道
大家在这篇2年前的帖子中讨论过各种类似做法:
http://www.iteye.com/topic/58834
你提出的想法是在约定大于配置上更进一步,少去了一些tag,如果更进一步,连#[]都可以省略,可以and开头,换行结尾作为匹配:
from HrOrganInfo where 1=1
and createDate>= ? and createDate<= ?
and ORGAN_NO like ?
and ORGAN_NAME like ?
and IS_ACTIVE = ?

不好意思,写这个东西前没有看过其它的写法,只是阿里的朋友给我展示ibatis时让我产生了灵感,我们已经用了好几个月了,大家用的非常舒服,sql在客户端写完粘进xml稍微改动一下就可以,要是修改拿出来改改就行,and这种是不现实的,嵌套什么的就非常麻烦,如何做到#[#[]]而且and 是sql中的字符这样做是不行的,一定需要找非常特殊的符号来约定。
0 请登录后投票
论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics