Hibernate如何实践union,order by,分页功能共存

来源:互联网 发布:js touchend事件 编辑:程序博客网 时间:2024/05/15 23:43

hibernate的  HQL是不支持union语句的。所以,我们只能使用原生态SQL语句来做~

[java] view plain copy
  1.   

问题是,不但要查出语句,还要封装成对象供应页面显示,这时,我们可以使用HQL的addScalar和setResultTransformer 来达到效果!

这就是所谓的标量查询,实际上,如果我们查询的两个表字段都一样对象一样的情况下,可以直接使用addEntity来把字段封装对象。在这里,

一个问题之一就是:union合并的字段不是都是来自同一个表。

[java] view plain copy
  1. StringBuffer sb  = new StringBuffer();  
  2.                      sb.append("( select sc.SCID as scid , sc.XN as xn , sc.XQ as xq , sc.XKKH as xkkh , sc.KCMC as kcmc , ");  
  3.                      sb.append(" sc.JXDW as jxdw , sc.XH as xh , sc.XM as xm , sc.XB as xb , sc.BJ as bj , sc.STATUS as status , ");  
  4.                      sb.append(" sc.QXZT as qxzt from STUDENTCHECK sc ");  
  5.                      sb.append(" where 1=1 and (sc.XN like ? ) ");  
  6.                      sb.append(" and sc.XQ=? ");  
  7.                      sb.append(" and sc.XKKH=? )");  
  8.                      sb.append(" union ");   
  9.                      sb.append("( select (case when cv.cvid=-1000000 then cv.cvid else null end) as scid , ");   
  10.                      sb.append(" substr(s.term,6,4) as xn , to_number(substr(s.term,11,1)) as xq , sc.xkkh as xkkh , ");   
  11.                      sb.append(" c.coursename as kcmc , stu.xy as jxdw , stu.XH as xh , stu.XM as xm , stu.xb as xb , ");   
  12.                      sb.append(" stu.xzb as bj , (case when cv.cvid = -1000000 then cv.cvid else 1 end) as status , ");   
  13.                      sb.append(" (case when cv.cvid = -1000000 then cv.cvid else 0 end) as qxzt ");   
  14.                      sb.append(" from CVARIABLE cv , SEMESTER s , STUBASICINFO stu , COURSE c,SCOURSE sc ");   
  15.                      sb.append(" where  cv.SID = s.SID and cv.SCID = sc.SCID and sc.xkkh = c.coursecode and cv.XH = stu.XH and 1=1 ");   
[java] view plain copy
  1.               sb.append(" and (stu.xh not in (select sc.xh from STUDENTCHECK sc where stu.xh= sc.xh))");  
  2. sb.append(" and (s.TERM like ? ) ");   
  3. sb.append(" and sc.XKKH = ? ");   


union查询出来的字段不能满足addEntity的条件。

需要强制转换。addScalar和setResultTransformer 的好处是,不需要所有的字段都要强制转换成对象。而,addEntiry必须是对象的所有对象,比如,sc.*

我们可以这样做。

[java] view plain copy
  1. Query query = session.createSQLQuery(hql)  
  2.                                             .addScalar("scid",Hibernate.LONG)  
  3.                                             .addScalar("xn", Hibernate.STRING)  
  4.                                             .addScalar("xq", Hibernate.INTEGER)  
  5.                                             .addScalar("xkkh",Hibernate.STRING)  
  6.                                             .addScalar("kcmc",Hibernate.STRING)  
  7.                                             .addScalar("jxdw",Hibernate.STRING)  
  8.                                             .addScalar("xh",Hibernate.STRING)  
  9.                                             .addScalar("xm",Hibernate.STRING)  
  10.                                             .addScalar("xb",Hibernate.INTEGER)  
  11.                                             .addScalar("bj",Hibernate.STRING)  
  12.                                             .addScalar("status",Hibernate.INTEGER)  
  13.                                             .addScalar("qxzt",Hibernate.INTEGER)  
  14.                                             .setResultTransformer(Transformers.aliasToBean(Studentcheck.class));  

还有一种方法:

Java代码  收藏代码
  1. Query q = session.createQuery("select new com.hibernate.MsgInfo(m.id, m.cont, m.topic.title, m.topic.category.name) from Msg m");    
  2. List<MsgInfo> list=q.list();    


其中,MsgInfo是DTO。值得注意的是,此方法中DTO必须提供带参数的构造方法,并且HQL语句中属性的位置要与构造方法中的位置一一对应。

union是有了!如何order by 呢?

例子:

(select * from Article where type=1 order by date desc limit 10)   union (select * from Article where type=3 order by date desc limit 10)

使用union最好把两个子查询都使用()括起来。

如果想对整体的联合结果进行排序分页的话则直接把order或者limit写到总执行语句的最后即可,当然这也是支持的数据库才行。

现在的问题之二:不但要union合并而且还要排序和分页


到这里了也许你相到了limit 的使用了!恭喜你,你想对了!

但是问题又来了,你使用的是什么数据库?

如果你使用Oracle,那么没办法,你遇到麻烦了!oracle不和别的数据库一样,limit的使用在Oracle是不能使用的。

这里主要针对的Oracle的union,order by,分页共存的问题

只能充分使用Oracle的rowid 和rownum变量来达到我们的想要的效果。

网络上对于Oracle模仿limit分页的方法:

[java] view plain copy
  1. select * from a_matrix_navigation_map  
  2.   
  3. where rowid not in(select rowid from a_matrix_navigation_map where rownum<=0) and rownum<=10  
  4.   
  5. 第二种:  
  6.   
  7. SELECT * FROM  
  8.   
  9. (  
  10.   
  11. SELECT A.*, rownum r  
  12.   
  13. FROM  
  14.   
  15. (  
  16.   
  17. SELECT *  
  18.   
  19. FROM a_matrix_navigation_map  
  20.   
  21. ) A  
  22.   
  23. WHERE rownum <= 10  
  24.   
  25. ) B  
  26.   
  27. WHERE r > 0  
  28.   
  29. 第三种  
  30.   
  31. SELECT * FROM table WHERE ROWNUM<101;  
  32.   
  33. minus  
  34.   
  35. SELECT * FROM table WHERE ROWNUM<91;  


然后你就会跟着做,如果你有试过的话,第一种方法就出现错误。简单例子的一个表情况Oracle的rowid和rownum还是比较清晰的。但是这是是union共用的。

这是实现了第二方式的分页的问题:

代码如下:

[java] view plain copy
  1. select t2.* from  (select t1.*,rownum rnum from  
  2.    ((select  
  3.        sc.SCID as scid,  
  4.        sc.XN as xn,  
  5.        sc.XQ as xq,  
  6.        sc.XKKH as xkkh,  
  7.        sc.KCMC as kcmc,  
  8.        sc.JXDW as jxdw,  
  9.        sc.XH as xh,  
  10.        sc.XM as xm,  
  11.        sc.XB as xb,  
  12.        sc.BJ as bj,  
  13.        sc.STATUS as status,  
  14.        sc.QXZT as qxzt  
  15.    from  
  16.        JISUANJI.STUDENTCHECK sc   
  17.    where  
  18.        1=1   
  19.        and (  
  20.            sc.XN like '%2014%'  
  21.        )   
  22.        and sc.XQ=2   
  23.        and sc.XKKH=34567896  
  24.        )  
  25.        union   
  26.        (  
  27.     select  
  28.    (case when cv.cvid=-1000000 then cv.cvid else null end) as scid,  
  29.    substr(s.term,6,4) as xn,  
  30.   to_number(substr(s.term,11,1)) as xq,  
  31.    sc.xkkh as xkkh,  
  32.    c.coursename as kcmc,  
  33.    stu.xy as jxdw,  
  34.    stu.XH as xh,  
  35.    stu.XM as xm,  
  36.    stu.xb as xb,  
  37.    stu.xzb as bj,  
  38.    (case when cv.cvid=-1000000 then cv.cvid else 1 end) as status,  
  39.    (case when cv.cvid=-1000000 then cv.cvid else 0 end) as qxzt  
  40. rom  
  41.    JISUANJI.CVARIABLE cv,  
  42.    JISUANJI.SEMESTER s,  
  43.    JISUANJI.SCOURSE sc,  
  44.    JISUANJI.STUBASICINFO stu,   
  45.    JISUANJI.COURSE c  
  46. here  
  47.    cv.SID=s.SID   
  48.    and cv.SCID=sc.SCID   
  49.    and sc.xkkh=c.coursecode  
  50.    and cv.XH=stu.XH   
  51.    and 1=1   
[java] view plain copy
  1. and (stu.xh not in (select sc.xh from STUDENTCHECK sc where stu.xh= sc.xh))  
  2. and (  
  3.     s.TERM like '%2013-2014-2%'  
  4. )   
  5. and sc.XKKH=34567896   
  6. and (  
  7.     stu.XZB like '%计算机2班%'   
  8.     or stu.XZB like '%计算机2班%'  
  9. ))) t1)t2  where t2.rnum>=1 and t2.rnum<=10  order by xh desc   


上面所述如有问题请留言共同探讨!


转自:http://blog.csdn.net/zhbitxhd/article/details/21801805

原创粉丝点击