Hibernate - DetachedCriteria 的完整用法

現(xiàn)在對 Hibernate的Criteria 的用法進(jìn)行總結(jié):

Hibernate 設(shè)計了 CriteriaSpecification 作為 Criteria 的父接口咏花,下面提供了 Criteria和DetachedCriteria 。Criteria 和 DetachedCriteria 的主要區(qū)別在于創(chuàng)建的形式不一樣棕硫, Criteria 是在線的洲敢,所以它是由 Hibernate Session 進(jìn)行創(chuàng)建的沉桌;而 DetachedCriteria 是離線的坦冠,創(chuàng)建時無需Session领迈,DetachedCriteria 提供了 2 個靜態(tài)方法 forClass(Class) 或 forEntityName(Name)進(jìn)行DetachedCriteria 實(shí)例的創(chuàng)建彻磁。 Spring 的框架提供了

getHibernateTemplate().findByCriteria(detachedCriteria)方法可以很方便地根據(jù)DetachedCriteria 來返回查詢結(jié)果。

Criteria 和 DetachedCriteria 均可使用 Criterion 和 Projection 設(shè)置查詢條件狸捅≈则眩可以設(shè)置 FetchMode( 聯(lián)合查詢抓取的模式 ) ,設(shè)置排序方式尘喝。對于 Criteria 還可以設(shè)置 FlushModel(沖刷 Session 的方式)和 LockMode (數(shù)據(jù)庫鎖模式)磁浇。

下面對 Criterion 和 Projection 進(jìn)行詳細(xì)說明。

Criterion 是 Criteria 的查詢條件朽褪。Criteria 提供了 add(Criterion criterion) 方法來添加查詢條件置吓。

Criterion 接口的主要實(shí)現(xiàn)包括: Example 无虚、 Junction 和 SimpleExpression 。而Junction 的實(shí)際使用是它的兩個子類 conjunction 和 disjunction 衍锚,分別是使用 AND 和 OR 操作符進(jìn)行來聯(lián)結(jié)查詢條件集合友题。

Criterion 的實(shí)例可以通過 Restrictions 工具類來創(chuàng)建,Restrictions 提供了大量的靜態(tài)方法构拳,如 eq (等于)咆爽、 ge (大于等于)、 between 等來方法的創(chuàng)建 Criterion 查詢條件(SimpleExpression 實(shí)例)置森。除此之外斗埂, Restrictions 還提供了方法來創(chuàng)建 conjunction 和disjunction 實(shí)例,通過往該實(shí)例的 add(Criteria) 方法來增加查詢條件形成一個查詢條件集合凫海。

至于 Example 的創(chuàng)建有所不同呛凶, Example 本身提供了一個靜態(tài)方法 create(Object?entity) ,即根據(jù)一個對象(實(shí)際使用中一般是映射到數(shù)據(jù)庫的對象)來創(chuàng)建行贪。然后可以設(shè)置一些過濾條件:

Example?exampleUser?=Example.create(u)//?忽略大小寫.ignoreCase()//?對?String?類型的屬性漾稀,無論在那里值在那里都匹配。相當(dāng)于?%value%.enableLike(MatchMode.ANYWHERE);

Project 主要是讓 Criteria 能夠進(jìn)行報表查詢建瘫,并可以實(shí)現(xiàn)分組崭捍。 Project 主要有SimpleProjection 、 ProjectionList 和 Property 三個實(shí)現(xiàn)啰脚。其中 SimpleProjection 和ProjectionList 的實(shí)例化是由內(nèi)建的 Projections 來完成殷蛇,如提供的 avg 、 count 橄浓、 max 粒梦、min 、 sum 可以讓開發(fā)者很容易對某個字段進(jìn)行統(tǒng)計查詢荸实。

Property 是對某個字段進(jìn)行查詢條件的設(shè)置匀们,如通過

Porperty.forName(“color”).in(new String[]{“black”,”red”,”write”}); 則可以創(chuàng)建一個 Project 實(shí)例。通criteria 的 add(Project) 方法加入到查詢條件中去准给。

使用 Criteria 進(jìn)行查詢泄朴,主要要清晰的是 Hibernate 提供了那些類和方法來滿足開發(fā)中查詢條件的創(chuàng)建和組裝,下面介紹幾種用法:

1. 創(chuàng)建一個Criteria 實(shí)例

org.hibernate.Criteria接口表示特定持久類的一個查詢露氮。Session是 Criteria實(shí)例的工廠叼旋。

Criteria?crit?=?sess.createCriteria(Cat.class);crit.setMaxResults(50);List?cats?=?crit.list();

2. 限制結(jié)果集內(nèi)容

一個單獨(dú)的查詢條件是org.hibernate.criterion.Criterion 接口的一個實(shí)例。

org.hibernate.criterion.Restrictions類 定義了獲得某些內(nèi)置Criterion類型的工廠方法沦辙。

List?cats?=?sess.createCriteria(Cat.class)?.add(?Restrictions.like("name","Fritz%")?)?.add(?Restrictions.between("weight",?minWeight,?maxWeight)?).list();

約束可以按邏輯分組夫植。

Listcats?=?sess.createCriteria(Cat.class)?.add(?Restrictions.like("name","Fritz%")?)?.add(?Restrictions.or(?????Restrictions.eq("age",newInteger(0)?),?????Restrictions.isNull("age")??)?).list();

List?cats?=?sess.createCriteria(Cat.class).add(?Restrictions.in("name",?new?String[]?{"Fritz","Izi","Pk"}?)?)?.add(?Restrictions.disjunction()?.add(?Restrictions.isNull("age")?)?.add(?Restrictions.eq("age",?new?Integer(0))?)?.add(?Restrictions.eq("age",?new?Integer(1))?)?.add(?Restrictions.eq("age",?new?Integer(2))?))?)?.list();

Hibernate提供了相當(dāng)多的內(nèi)置criterion類型(Restrictions 子類), 但是尤其有用的是可以允許你直接使用SQL。

List?cats?=?sess.createCriteria(Cat.class).add(?Restrictions.sql("lower({alias}.name)?like?lower(?)","Fritz%",Hibernate.STRING)?)?.list();

{alias}占位符應(yīng)當(dāng)被替換為被查詢實(shí)體的列別名。

Property實(shí)例是獲得一個條件的另外一種途徑详民。你可以通過調(diào)用Property.forName() 創(chuàng)建一個Property延欠。

Property?age?=?Property.forName("age");List?cats?=?sess.createCriteria(Cat.class)?.add(?Restrictions.disjunction()?????.add(?age.isNull()?)?????.add(?age.eq(?new?Integer(0))?)?????.add(?age.eq(?new?Integer(1))?)?????.add(?age.eq(?new?Integer(2))?)?)?)?.add(?Property.forName("name").in(?new?String[]?{"Fritz","Izi","Pk"}?)?)?.list();

3. 結(jié)果集排序

你可以使用org.hibernate.criterion.Order來為查詢結(jié)果排序。

List?cats?=?sess.createCriteria(Cat.class)?.add(?Restrictions.like("name","F%")?.addOrder(?Order.asc("name")?)?.addOrder(?Order.desc("age")?)?.setMaxResults(50).list();

List?cats?=?sess.createCriteria(Cat.class)????.add(?Property.forName("name").like("F%")?)????.addOrder(?Property.forName("name").asc()?)????.addOrder(?Property.forName("age").desc()?)????.setMaxResults(50)??.list();

4. 關(guān)聯(lián)

你可以使用createCriteria()非常容易的在互相關(guān)聯(lián)的實(shí)體間建立 約束沈跨。

List?cats?=?sess.createCriteria(Cat.class).add(?Restrictions.like("name","F%").createCriteria("kittens").add(?Restrictions.like("name","F%").list();

注意第二個 createCriteria()返回一個新的 Criteria實(shí)例由捎,該實(shí)例引用kittens 集合中的元素。

接下來饿凛,替換形態(tài)在某些情況下也是很有用的狞玛。

List?cats?=?sess.createCriteria(Cat.class)????.createAlias("kittens","kt")????.createAlias("mate","mt")????.add(?Restrictions.eqProperty("kt.name","mt.name")?)????.list();

(createAlias()并不創(chuàng)建一個新的 Criteria實(shí)例。)

Cat實(shí)例所保存的之前兩次查詢所返回的kittens集合是 沒有被條件預(yù)過濾的涧窒。如果你希望只獲得

符合條件的kittens心肪, 你必須使用returnMaps()。

Listcats?=?sess.createCriteria(Cat.class)????.createCriteria("kittens","kt")????.add(Restrictions.eq("name","F%")?)????.returnMaps()????.list();Iteratoriter?=?cats.iterator();while(?iter.hasNext()?)?{Mapmap=?(Map)?iter.next();Catcat?=?(Cat)map.get(Criteria.ROOT_ALIAS);Catkitten?=?(Cat)map.get("kt");}

5. 動態(tài)關(guān)聯(lián)抓取

你可以使用setFetchMode()在運(yùn)行時定義動態(tài)關(guān)聯(lián)抓取的語義纠吴。

List?cats?=?sess.createCriteria(Cat.class)????.add(?Restrictions.like("name","Fritz%")?)????.setFetchMode("mate",?FetchMode.EAGER)????.setFetchMode("kittens",?FetchMode.EAGER)????.list();

這個查詢可以通過外連接抓取mate和kittens硬鞍。

6. 查詢示例

org.hibernate.criterion.Example類允許你通過一個給定實(shí)例 構(gòu)建一個條件查詢。

Cat?cat?=newCat();cat.setSex('F');cat.setColor(Color.BLACK);List?results?=?session.createCriteria(Cat.class).add(?Example.create(cat)?).list();

版本屬性戴已、標(biāo)識符和關(guān)聯(lián)被忽略固该。默認(rèn)情況下值為null的屬性將被排除。

可以自行調(diào)整Example使之更實(shí)用糖儡。

Example?example?=?Example.create(cat)????.excludeZeroes()//exclude?zero?valued?properties.excludeProperty("color")//exclude?the?property?named?"color".ignoreCase()//perform?case?insensitive?string?comparisons.enableLike();//use?like?for?string?comparisonsList?results?=?session.createCriteria(Cat.class)????.add(example).list();

甚至可以使用examples在關(guān)聯(lián)對象上放置條件伐坏。

List?results?=?session.createCriteria(Cat.class)????.add(?Example.create(cat)?)????.createCriteria("mate")????.add(?Example.create(?cat.getMate()?)?)????.list();

7. 投影(Projections)、聚合(aggregation)和分組(grouping)

org.hibernate.criterion.Projections是 Projection 的實(shí)例工廠握联。我們通過調(diào)用setProjection()應(yīng)用投影到一個查詢桦沉。

List?results?=?session.createCriteria(Cat.class)????.setProjection(?Projections.rowCount()?)????.add(?Restrictions.eq("color",?Color.BLACK))????.list();

List?results?=?session.createCriteria(Cat.class)????.setProjection(?Projections.projectionList()????????.add(?Projections.rowCount()?)????????.add(?Projections.avg("weight")?)????????.add(?Projections.max("weight")?)????????.add(?Projections.groupProperty("color")?)????)?.list();

在一個條件查詢中沒有必要顯式的使用 "group by" 。某些投影類型就是被定義為 分組投影拴疤,他們也出現(xiàn)在SQL的group by子句中。

可以選擇把一個別名指派給一個投影独泞,這樣可以使投影值被約束或排序所引用呐矾。下面是兩種不同的實(shí)現(xiàn)方式:

List?results?=?session.createCriteria(Cat.class)????.setProjection(?Projections.alias(?Projections.groupProperty("color"),"colr")?)????.addOrder(?Order.asc("colr")?).list();

Listresults?=?session.createCriteria(Cat.class)????.setProjection(?Projections.groupProperty("color").as("colr")?)????.addOrder(?Order.asc("colr")?).list();

alias()和as()方法簡便的將一個投影實(shí)例包裝到另外一個 別名的Projection實(shí)例中。簡而言之懦砂,

當(dāng)你添加一個投影到一個投影列表中時 你可以為它指定一個別名:

List?results?=?session.createCriteria(Cat.class)????.setProjection(?Projections.projectionList()????????.add(?Projections.rowCount(),"catCountByColor")????????.add(?Projections.avg("weight"),"avgWeight")????????.add(?Projections.max("weight"),"maxWeight")????????.add(?Projections.groupProperty("color"),"color")????)????.addOrder(?Order.desc("catCountByColor")?)????.addOrder(?Order.desc("avgWeight")?).list();

List?results?=?session.createCriteria(Domestic.class,"cat")????.createAlias("kittens","kit")????.setProjection(?Projections.projectionList()????????.add(?Projections.property("cat.name"),"catName")????????.add(?Projections.property("kit.name"),"kitName")????)????.addOrder(?Order.asc("catName")?)????.addOrder(?Order.asc("kitName")?)????.list();

也可以使用Property.forName()來表示投影:

List?results?=?session.createCriteria(Cat.class)????.setProjection(?Property.forName("name")?)????.add(?Property.forName("color").eq(Color.BLACK))????.list();

Listresults?=?session.createCriteria(Cat.class)????.setProjection(?Projections.projectionList()????????.add(?Projections.rowCount().as("catCountByColor")?)????????.add(?Property.forName("weight").avg().as("avgWeight")?)????????.add(?Property.forName("weight").max().as("maxWeight")?)????????.add(?Property.forName("color").group().as("color")????)????.addOrder(?Order.desc("catCountByColor")?)????.addOrder(?Order.desc("avgWeight")?)????.list();

8. 離線(detached)查詢和子查詢

DetachedCriteria類使你在一個session范圍之外創(chuàng)建一個查詢蜒犯,并且可以使用任意的?Session來執(zhí)行它。DetachedCriteria?query?=?DetachedCriteria.forClass(Cat.class)????.add(?Property.forName("sex").eq('F'));//創(chuàng)建一個SessionSession?session?=?Transaction?txn?=?session.beginTransaction();List?results?=?query.getExecutableCriteria(session).setMaxResults(100).list();txn.commit();session.close();

DetachedCriteria也可以用以表示子查詢荞膘。條件實(shí)例包含子查詢可以通過 Subqueries或者Property獲得罚随。

DetachedCriteria?avgWeight?=?DetachedCriteria.forClass(Cat.class)????.setProjection(?Property.forName("weight").avg()?);session.createCriteria(Cat.class)????.add(?Property.forName("weight).gt(avgWeight)?)

.list();

DetachedCriteria?weights?=?DetachedCriteria.forClass(Cat.class)

.setProjection(?Property.forName("weight")?);

session.createCriteria(Cat.class)

.add(?Subqueries.geAll("weight",?weights)?)

.list();

相互關(guān)聯(lián)的子查詢也是有可能的:

DetachedCriteria?avgWeightForSex?=?DetachedCriteria.forClass(Cat.class,"cat2")????.setProjection(?Property.forName("weight").avg()?)????.add(?Property.forName("cat2.sex").eqProperty("cat.sex")?);session.createCriteria(Cat.class,"cat")????.add(?Property.forName("weight).gt(avgWeightForSex)?)

.list();

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市羽资,隨后出現(xiàn)的幾起案子淘菩,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件潮改,死亡現(xiàn)場離奇詭異狭郑,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)汇在,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進(jìn)店門翰萨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人糕殉,你說我怎么就攤上這事亩鬼。” “怎么了阿蝶?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵雳锋,是天一觀的道長。 經(jīng)常有香客問我赡磅,道長魄缚,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任焚廊,我火速辦了婚禮冶匹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘咆瘟。我一直安慰自己嚼隘,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布袒餐。 她就那樣靜靜地躺著飞蛹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪灸眼。 梳的紋絲不亂的頭發(fā)上卧檐,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天,我揣著相機(jī)與錄音焰宣,去河邊找鬼霉囚。 笑死,一個胖子當(dāng)著我的面吹牛匕积,可吹牛的內(nèi)容都是我干的盈罐。 我是一名探鬼主播,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼闪唆,長吁一口氣:“原來是場噩夢啊……” “哼盅粪!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起悄蕾,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤票顾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體库物,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡霸旗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了戚揭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诱告。...
    茶點(diǎn)故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖民晒,靈堂內(nèi)的尸體忽然破棺而出精居,到底是詐尸還是另有隱情,我是刑警寧澤潜必,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布靴姿,位于F島的核電站,受9級特大地震影響磁滚,放射性物質(zhì)發(fā)生泄漏佛吓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一垂攘、第九天 我趴在偏房一處隱蔽的房頂上張望维雇。 院中可真熱鬧,春花似錦晒他、人聲如沸吱型。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽津滞。三九已至,卻和暖如春灼伤,著一層夾襖步出監(jiān)牢的瞬間触徐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工狐赡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留撞鹉,地道東北人。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓猾警,卻偏偏與公主長得像孔祸,于是被迫代替她去往敵國和親隆敢。 傳聞我的和親對象是個殘疾皇子发皿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評論 2 354

推薦閱讀更多精彩內(nèi)容