以前寫(xiě)hibernate查詢的時(shí)候都是萬(wàn)年不變的HQL語(yǔ)句查詢,實(shí)在不行的就返璞歸真進(jìn)行SQL查詢,這兩天寫(xiě)代碼的時(shí)候見(jiàn)到了criteria的查詢方式,覺(jué)得挺好使,就在網(wǎng)上查查資料,項(xiàng)目里面的功能是完成了,但是對(duì)這個(gè)criteria的使用還是不是很熟練,建個(gè)小工程搭個(gè)hibernate,一邊看資料一邊做測(cè)試順便寫(xiě)個(gè)博客記錄一下,一舉三得有木有。
Hibernate 定義了Criteriaspecification接口規(guī)范用來(lái)完成面向?qū)ο蟮臈l件查詢,Criteria 就是CriteriaSpecification的子接口。使用criteria時(shí),你不需要去關(guān)心SQL語(yǔ)句,我想這對(duì)于SQL語(yǔ)句不太好的人來(lái)說(shuō)是個(gè)最大的好處,好了廢話不多說(shuō),下面進(jìn)入主題。
1、創(chuàng)建CriteriaCriteria的實(shí)現(xiàn)是離不開(kāi)session的,也就是說(shuō)Criteria的生命周期隨著session的生命周期的結(jié)束而結(jié)束,在使用Criteria進(jìn)行查詢的時(shí)候,每次都要在執(zhí)行時(shí)期動(dòng)態(tài)建立物件,并且加入各種查詢條件,如果session回收了,那么Criteria也跟著回收。
Criteria的創(chuàng)建如下:
Criteria criteria = session.createCriteria(User1.class);
User1.class表示你要查詢的那個(gè)實(shí)體類。
2、Criteria查詢2.1@Test public void test() { Criteria criteria = session.createCriteria(User1.class); List<User1> list = criteria.list(); for(User1 u: list){ System.out.PRintln(u.toString()); } }
上述的方式就是Criteria的查詢方式,創(chuàng)建好Criteria之后,只要使用Criteria.list()方法即可查詢到你要查詢的實(shí)體的數(shù)據(jù)集合,可以看一下hibernate發(fā)出的sql語(yǔ)句:
Hibernate: select this_.uid as uid0_0_, this_.username as username0_0_, this_.pwd as pwd0_0_, this_.create_date as create4_0_0_ from test.t_user1 this_
這個(gè)跟我們寫(xiě)HQL語(yǔ)句查詢時(shí)hibernate發(fā)出的sql語(yǔ)句是一樣。
2.2但是上面的查詢是對(duì)查詢出了全部的數(shù)據(jù),有時(shí)候這并不是我們想要的,比如說(shuō)我現(xiàn)在想查出姓張的用戶?這時(shí)候就需要使用Criteria方式添加條件了,先看一個(gè)代碼演示:
@Test public void test() { Criteria criteria = session.createCriteria(User1.class); criteria.add(Restrictions.like("name", "%張%")); List<User1> list = criteria.list(); for(User1 u: list){ System.out.println(u.toString()); } }
此時(shí)的查詢結(jié)果就是名字中帶有張字的用戶,上面說(shuō)的姓張的用戶并不準(zhǔn)確,這就是一個(gè)模糊查詢,like像的意思,也就是說(shuō)在告訴criteria在查詢的時(shí)候給我找出來(lái)名字帶張字的,看我不揍死他們,就這意思。
此時(shí)控制臺(tái)發(fā)出的sql語(yǔ)句如下:
Hibernate: select this_.uid as uid0_0_, this_.username as username0_0_, this_.pwd as pwd0_0_, this_.create_date as create4_0_0_ from test.t_user1 this_ where this_.username like ?
要注意的地方有幾個(gè):第一,like后面的兩個(gè)參數(shù),第一個(gè)參數(shù)是實(shí)體類中對(duì)應(yīng)的要查詢的字段,第二個(gè)參數(shù)是查詢的條件。
第二,模糊查詢可以用like,但是等于查詢就是eq、大于等于是ge、between表示兩者之間等等,這個(gè)在使用的時(shí)候需要注意一下,不同的查詢使用不同的可以叫做方法吧。
第三,添加條件的時(shí)候都是使用的criteria.add(),這個(gè)方法是沒(méi)有什么變化的。
第四,Restrictions是一個(gè)工具類,提供了大量的靜態(tài)方法,比如上面的like(),eq()等。
2.3上面的查詢條件是只有一個(gè),那如果現(xiàn)在我有多個(gè)查詢條件怎么辦呢?這個(gè)也好辦,使用多個(gè)criteria.add()方法來(lái)滿足多條件的查詢,并且這多個(gè)條件之間屬于and的關(guān)系,如下所示:
@Test public void test() { Criteria criteria = session.createCriteria(User1.class); criteria.add(Restrictions.like("name", "%張%")); criteria.add(Restrictions.eq("passWord", "123")); List<User1> list = criteria.list(); for(User1 u: list){ System.out.println(u.toString()); } }
上面的查詢什么意思呢?意思就是在查找名字中帶有張字的同時(shí)還要滿足密碼是123的,兩個(gè)條件之間屬于并列關(guān)系,可以看一下hibernate發(fā)出的查詢語(yǔ)句:
Hibernate: select this_.uid as uid0_0_, this_.username as username0_0_, this_.pwd as pwd0_0_, this_.create_date as create4_0_0_ from test.t_user1 this_ where this_.username like ? and this_.pwd=?2.4
現(xiàn)在需求又變了,怎么變了呢?我現(xiàn)在不查名字里面帶張字的了,我現(xiàn)在知道倆密碼,一個(gè)123,一個(gè)234,就查密碼是123或者234的用戶,這時(shí)候怎么查啊?倆條件我寫(xiě)倆criteria.add()方法嗎?但是這倆是屬于and關(guān)系啊,怎么搞?看下面的代碼:
@Test public void test() { Criteria criteria = session.createCriteria(User1.class); //criteria.add(Restrictions.like("name", "%張%")); //criteria.add(Restrictions.eq("password", "123")); criteria.add(Restrictions.or( Restrictions.eq("password", "123"), Restrictions.eq("password", "234"))); List<User1> list = criteria.list(); for(User1 u: list){ System.out.println(u.toString()); } }
再看一下hibernate發(fā)出的sql語(yǔ)句:
Hibernate: select this_.uid as uid0_0_, this_.username as username0_0_, this_.pwd as pwd0_0_, this_.create_date as create4_0_0_ from test.t_user1 this_ where (this_.pwd=? or this_.pwd=?)
可以看到sql語(yǔ)句最后是pwd=? or pwd = ?,進(jìn)行的是或查詢,怎么實(shí)現(xiàn)的呢?就是Restrictions.or()方法,表示或的意思,里面的兩個(gè)參數(shù)又是兩個(gè)表達(dá)式,between操作與or操作差不多,大家試一下就會(huì)了,我就不再?gòu)U話了。
2.5列一下常用的常用的幾個(gè)Restrictions方法:
Restrictions.eq 等于 Restrictions.allEq 使用Map,使用key/value進(jìn)行多個(gè)等于的比對(duì) Restrictions.gt 大于 > Restrictions.ge 大于等于 >= Restrictions.lt 小于 < Restrictions.le 小于等于 <= Restrictions.between 對(duì)應(yīng)SQL的BETWEEN子句 Restrictions.like 對(duì)應(yīng)SQL的LIKE子句 Restrictions.in 對(duì)應(yīng)SQL的in子句 Restrictions.and and關(guān)系 Restrictions.or or關(guān)系
3.criteria 排序、統(tǒng)計(jì)、分組等功能3.1 排序在使用criteria查詢結(jié)果集的時(shí)候是可以對(duì)所查詢的數(shù)據(jù)進(jìn)行排序的,怎么做呢?看下面:
@Test public void test() { Criteria criteria = session.createCriteria(User1.class); criteria.addOrder(Order.asc("name")); List<User1> list = criteria.list(); for(User1 u: list){ System.out.println(u.toString()); } }
hibernate發(fā)出的sql語(yǔ)句:
Hibernate: select this_.uid as uid0_0_, this_.username as username0_0_, this_.pwd as pwd0_0_, this_.create_date as create4_0_0_ from test.t_user1 this_ order by this_.username asc
可以看到是根據(jù)用戶名進(jìn)行正序排序,如果是倒序排列呢,只需要把a(bǔ)sc換成desc就可以了,就是這么任性,但是要注意,此時(shí)添加的排序條件是使用的是criteria.addOrder()方法,而不是criteria.add().
3.2 偽分頁(yè)為什么叫偽分頁(yè)呢,我這里就是做一個(gè)簡(jiǎn)單的演示操作,跟分頁(yè)扯不上什么關(guān)系,只不過(guò)查詢方法類似于分頁(yè)的查詢方法而已,所以我起名叫偽分頁(yè),不過(guò)這個(gè)應(yīng)該有具體的名字吧,不過(guò)我也不知道到底叫什么,就隨便叫吧,大家看了代碼就知道我說(shuō)的是什么了。
@Test public void test() { Criteria criteria = session.createCriteria(User1.class); //criteria.addOrder(Order.asc("name")); criteria.setFirstResult(1); criteria.setMaxResults(3); List<User1> list = criteria.list(); for(User1 u: list){ System.out.println(u.toString()); } }
上sql語(yǔ)句:
Hibernate: select this_.uid as uid0_0_, this_.username as username0_0_, this_.pwd as pwd0_0_, this_.create_date as create4_0_0_ from test.t_user1 this_ limit ?, ?
看了上面的代碼大家有沒(méi)有覺(jué)得跟寫(xiě)分頁(yè)時(shí)候的從第幾條記錄開(kāi)始,每次顯示多少條記錄很像。
今天有事,先總結(jié)到這,下次再繼續(xù)總結(jié)。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注