ITPUB论坛-专业的IT技术社区

标题: 数据库动态查询最佳实现 陈氏查询 [打印本页]

作者: zhongxuchen    时间: 2009-4-26 18:19
标题: 数据库动态查询最佳实现 陈氏查询
我占个位,命名为陈氏查询!一帮所谓牛人总说不是什么创新,为我的“陈氏查询”名称感到很不爽!但他们所提供的证据范例个人认为连ibatis的做法都不如,反增加了开发的麻烦!
还是开门见山,本文所要介绍的是针对数据库查询(当然要是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的写法非常的优雅,结构完整!
同时#[]支持嵌套,如:
#[]相当于if判断
select  t.*
from table_name t
where 1 = 1   
           and t.type=:type
          #[and t.status=:status   
             and t.orderId=(select orderId   
                                     from t2
                                     #[where t2.name  like :name]
                                      )
             ]  

调用方法:
   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,SqlUtil.filterEquals(status,"-1")}, pageModel,OrganInfoVO.class);
提供java反射器直接映射成VO,也提供了RowCallbackHandler通过反调方式生成VO,当然voClass和RowCallbackHandler都为null,就直接返回数组集合!

目前增加了缓存机制
一句分页查询就这么简单:
return this.findPageByJdbc("security_findRole", null, new Object[] {
    SqlUtil.filterEqual(roleVO.getActiveFlag(), SystemConstants.FULL),
    SqlUtil.filterEqual(roleVO.getLayerFlag(),  SystemConstants.FULL),
    SqlUtil.filterBlank(roleVO.getAllRoleNos()) }, pageModel, RoleVO.class);

如果你想藐视请你拿出你的写法,要是更简单我服你,要是觉得不错请回帖顶一下(实在是看到太多没有看明白就否定一切的人)


[ 本帖最后由 zhongxuchen 于 2009-6-23 17:34 编辑 ]
作者: Sky-Tiger    时间: 2009-4-26 18:37
GOOD!
作者: freedom2k    时间: 2009-4-27 23:40
恩有空得仔细看看
作者: 图腾部落    时间: 2009-4-28 14:37
多谢分享
作者: dreamzdf    时间: 2009-4-29 09:56
不错
作者: justforregister    时间: 2009-4-30 22:34
干了这么多年, 还没写过sql, 郁闷
作者: piliskys    时间: 2009-5-1 21:28
不想打击楼主,这点东西还能跟ibatis相提并论,
随便写个变量替代估计比你这个都强, 没有最好,只要适合自己项目,自己使用规则就好
作者: zhongxuchen    时间: 2009-5-2 14:51
你看清楚了文章没有呀?没有说全部跟ibatis比,但查询时比ibatis好的,你怎么打击我也没有用呀,ibatis的动态查询就是没有我这个优雅呀,ibatis我也用过呀!sql结构打乱了,我这个也是支持参数命名的,请看清楚再回复(顺便再提醒一下,不仅仅是sql、hql等等的都一样支持)
select  t.*
from table_name t
where 1 = 1   
           and t.type=:type
          #[and t.status=:status   
             and t.orderId=(select orderId   
                                     from t2
                                     #[where t2.name  like :name]
                                      )
             ]
作者: piliskys    时间: 2009-5-2 16:34
呵呵,的确,打击别人永远是错误的,
我写sql及存储过程语句比写java代码要多的多, 你说的参数命名spring的 NamedParameterJdbcTemplate 都有这方法的(估计比你这个要强大,直接支持数组),
而且自己实现也基本是相当容易, 任何的定制的sql在项目中都有可能会不够用, 如果谈优雅,最好是开发人员都不用参与sql的编写,自动生成如果能达到80%的够用的话,那样也就够了, 有时候封装的方法并不一定是我们所要的,我们对数据库的结果有时并不需要是转好的List,而只是要一原始的ResultSet。 个人认为,自动生成数据库对象操作解决80%的问题,增删改及一些单表操作肯定是可以实现自动化的,其它20%,那就自己写sql吧,想怎么灵活就怎么灵活,一切在于规范及能力控制中.
一句话,如果你认为自己的架构或设计好,那一定要建立在开发人员之上, 当开发人员用此架构及设计时,不需要知道其中的约束,不清楚自己用的是什么,只是觉得好用,那就是成功的。
作者: gargoyle    时间: 2009-5-4 23:34
学习。
作者: zhongxuchen    时间: 2009-5-5 00:27
标题: 回复 #9 piliskys 的帖子
哈哈,不是打击不打击的事情,我认为你根本就没有看明白我说的是什么,我强调的是sql的写法,动态参数,我提供的是对sql语句的动态处理
查询条件不定,最终执行的sql是不一样的,你说的跟我说的不是一码事,我强调的是动态以及sql和代码的分离,你确信明白了再提打击!不要没有看明白什么意思,上来就搞什么打击,这样是不对的!
请看这句:老兄你说的支持数组,请看文章调用方法那块,其实调用时及其简单的就是一句话!你说的对返回数据的封装,我告诉你我提供了3种方式:
在调用时提供了多态方式参数有voClass、rowCallBackHandler(反调自己实现接口,spring jdbcTemplate中有类似实现,请参看),如果这两个参数都为null就返回数组集合,我想这应该完全满足要求了吧?要快速对象封装就用voClass,比较复杂的封装就自己实现RowCallBackHandler接口,如果不需要封装就什么也不传,直接返回ResultSet放到List中的结果,哈哈这里不多阐述了,我非常希望大家能够认真阅读后再提出自己的见解,不要仅看一眼就随意评价,好坏自有分说,我乐意听到不同的声音,但没有看明白意思就评说我认为缺乏严谨的做事态度,对我的文章也不够尊重!
select t.*
          ,t1.NAME
from OA_CAR_REGIST t,HR_STAFF_INFO t1
where 1=1
         and t1.STAFF_NO=t.CHAUFFEUR
         and t.IS_ACTIVE=?
         #[and t.CAR_MODE like ? ] <!--?对应的值为null 这一块就没有了,这不是spring里面所提供的吧--->
         #[and t1.NAME like ? ]
         #[and t.REGIST_DATE>=? and t.REGIST_DATE<= ? ]
         #[and t.DISABLE_DATE>=? and t.DISABLE_DATE<= ? ]
         #[and t.ASSET_TYPE= ? ]
这样的sql判断参数值,#[]中的内容有可能会被切除,也许最终的sql是:
select t.*
          ,t1.NAME
from OA_CAR_REGIST t,HR_STAFF_INFO t1
where 1=1
         and t1.STAFF_NO=t.CHAUFFEUR
         and t.IS_ACTIVE=?

select t.*
          ,t1.NAME
from OA_CAR_REGIST t,HR_STAFF_INFO t1
where 1=1
         and t1.STAFF_NO=t.CHAUFFEUR
         and t.IS_ACTIVE=?
         and t.ASSET_TYPE= ?


要是老兄果然是没有看明白,那我真为自己叫屈,我真是服了,太多人都是对待事情是不踏实严谨,你还算不错了,javaeye上的有一个上来就声称写sql就是过时(当然我的这个也是支持hql等等的,这小子根本就没有明白我所阐述的一个机理),还有就是把别人想的特土,hibernate的条件查询还有this.getHibernateTemplate.get(Id)之类的别人也不知道一样,我当时还特别在文章头上说了,简单的做法不多强调,因为简单的大家做法都差不多,写在代码中也无所谓!更有甚者以用了hibernate annotation就标榜自己先进!我真服了!

[ 本帖最后由 zhongxuchen 于 2009-5-5 00:59 编辑 ]
作者: zhongxuchen    时间: 2009-5-5 00:28
标题: 回复 #9 piliskys 的帖子
哈哈,不是打击不打击的事情,我认为你根本就没有看明白我说的是什么,我强调的是sql的写法,动态参数,我提供的是对sql语句的动态处理,
查询条件不定,最终执行的sql是不一样的,你说的跟我说的不是一码事,我强调的是动态以及sql和代码的分离,你确信明白了再提打击!不要没有看明白什么意思,上来就搞什么打击,这样是不对的!
select t.*
          ,t1.NAME
from OA_CAR_REGIST t,HR_STAFF_INFO t1
where 1=1
         and t1.STAFF_NO=t.CHAUFFEUR
         and t.IS_ACTIVE=?
         #[and t.CAR_MODE like ? ] <!--?对应的值为null 这一块就没有了,这不是spring里面所提供的吧--->
         #[and t1.NAME like ? ]
         #[and t.REGIST_DATE>=? and t.REGIST_DATE<= ? ]
         #[and t.DISABLE_DATE>=? and t.DISABLE_DATE<= ? ]
         #[and t.ASSET_TYPE= ? ]
这样的sql判断参数值,#[]中的内容有可能会被切除,




欢迎光临 ITPUB论坛-专业的IT技术社区 (http://www.itpub.net/) Powered by Discuz! X3.2