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合併而且還要排序和分頁
但是問題又來了,你使用的是什麼數據庫?
如果你使用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;
這是實現了第二方式的分頁的問題:
代碼如下:
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