Hibernate如何實踐union,order by,分頁功能共存

hibernate的  HQL是不支持union語句的。所以,我們只能使用原生態SQL語句來做~

問題是,不但要查出語句,還要封裝成對象供應頁面顯示,這時,我們可以使用HQL的addScalar和setResultTransformer 來達到效果!

這就是所謂的標量查詢,實際上,如果我們查詢的兩個表字段都一樣對象一樣的情況下,可以直接使用addEntity來把字段封裝對象。在這裏,

一個問題之一就是:union合併的字段不是都是來自同一個表。

StringBuffer sb  = new StringBuffer();
		             sb.append("( select sc.SCID as scid , sc.XN as xn , sc.XQ as xq , sc.XKKH as xkkh , sc.KCMC as kcmc , ");
		             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 , ");
		             sb.append(" sc.QXZT as qxzt from STUDENTCHECK sc ");
		             sb.append(" where 1=1 and (sc.XN like ? ) ");
		             sb.append(" and sc.XQ=? ");
		             sb.append(" and sc.XKKH=? )");
		             sb.append(" union "); 
		             sb.append("( select (case when cv.cvid=-1000000 then cv.cvid else null end) as scid , "); 
		             sb.append(" substr(s.term,6,4) as xn , to_number(substr(s.term,11,1)) as xq , sc.xkkh as xkkh , "); 
		             sb.append(" c.coursename as kcmc , stu.xy as jxdw , stu.XH as xh , stu.XM as xm , stu.xb as xb , "); 
		             sb.append(" stu.xzb as bj , (case when cv.cvid = -1000000 then cv.cvid else 1 end) as status , "); 
		             sb.append(" (case when cv.cvid = -1000000 then cv.cvid else 0 end) as qxzt "); 
		             sb.append(" from CVARIABLE cv , SEMESTER s , STUBASICINFO stu , COURSE c,SCOURSE sc "); 
		             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 "); 
                             sb.append(" and (stu.xh not in (select sc.xh from STUDENTCHECK sc where stu.xh= sc.xh))");
		             sb.append(" and (s.TERM like ? ) "); 
		             sb.append(" and sc.XKKH = ? "); 


union查詢出來的字段不能滿足addEntity的條件。

需要強制轉換。addScalar和setResultTransformer 的好處是,不需要所有的字段都要強制轉換成對象。而,addEntiry必須是對象的所有對象,比如,sc.*

我們可以這樣做。

Query query = session.createSQLQuery(hql)
					                        .addScalar("scid",Hibernate.LONG)
					                        .addScalar("xn", Hibernate.STRING)
					                        .addScalar("xq", Hibernate.INTEGER)
					                        .addScalar("xkkh",Hibernate.STRING)
					                        .addScalar("kcmc",Hibernate.STRING)
					                        .addScalar("jxdw",Hibernate.STRING)
					                        .addScalar("xh",Hibernate.STRING)
					                        .addScalar("xm",Hibernate.STRING)
					                        .addScalar("xb",Hibernate.INTEGER)
					                        .addScalar("bj",Hibernate.STRING)
					                        .addScalar("status",Hibernate.INTEGER)
					                        .addScalar("qxzt",Hibernate.INTEGER)
					                        .setResultTransformer(Transformers.aliasToBean(Studentcheck.class));

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分頁的方法:

select * from a_matrix_navigation_map

where rowid not in(select rowid from a_matrix_navigation_map where rownum<=0) and rownum<=10

第二種:

SELECT * FROM

(

SELECT A.*, rownum r

FROM

(

SELECT *

FROM a_matrix_navigation_map

) A

WHERE rownum <= 10

) B

WHERE r > 0

第三種

SELECT * FROM table WHERE ROWNUM<101;

minus

SELECT * FROM table WHERE ROWNUM<91;


然後你就會跟着做,如果你有試過的話,第一種方法就出現錯誤。簡單例子的一個表情況Oracle的rowid和rownum還是比較清晰的。但是這是是union共用的。

這是實現了第二方式的分頁的問題:

代碼如下:

     select t2.* from  (select t1.*,rownum rnum from
        ((select
            sc.SCID as scid,
            sc.XN as xn,
            sc.XQ as xq,
            sc.XKKH as xkkh,
            sc.KCMC as kcmc,
            sc.JXDW as jxdw,
            sc.XH as xh,
            sc.XM as xm,
            sc.XB as xb,
            sc.BJ as bj,
            sc.STATUS as status,
            sc.QXZT as qxzt
        from
            JISUANJI.STUDENTCHECK sc 
        where
            1=1 
            and (
                sc.XN like '%2014%'
            ) 
            and sc.XQ=2 
            and sc.XKKH=34567896
            )
            union 
            (
         select
        (case when cv.cvid=-1000000 then cv.cvid else null end) as scid,
        substr(s.term,6,4) as xn,
       to_number(substr(s.term,11,1)) as xq,
        sc.xkkh as xkkh,
        c.coursename as kcmc,
        stu.xy as jxdw,
        stu.XH as xh,
        stu.XM as xm,
        stu.xb as xb,
        stu.xzb as bj,
        (case when cv.cvid=-1000000 then cv.cvid else 1 end) as status,
        (case when cv.cvid=-1000000 then cv.cvid else 0 end) as qxzt
    from
        JISUANJI.CVARIABLE cv,
        JISUANJI.SEMESTER s,
        JISUANJI.SCOURSE sc,
        JISUANJI.STUBASICINFO stu, 
        JISUANJI.COURSE c
    where
        cv.SID=s.SID 
        and cv.SCID=sc.SCID 
        and sc.xkkh=c.coursecode
        and cv.XH=stu.XH 
        and 1=1 
        and (stu.xh not in (select sc.xh from STUDENTCHECK sc where stu.xh= sc.xh))
        and (
            s.TERM like '%2013-2014-2%'
        ) 
        and sc.XKKH=34567896 
        and (
            stu.XZB like '%計算機2班%' 
            or stu.XZB like '%計算機2班%'
        ))) t1)t2  where t2.rnum>=1 and t2.rnum<=10  order by xh desc 


上面所述如有問題請留言共同探討!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章