【正文】
知道結(jié)果是單個(gè),我們可以用getSingleResult()獲得結(jié)果 final Object result = ()。 // 由于Order中id的類型為long, final Long max = (Long)result。 // 在一些數(shù)據(jù)庫(kù)中max函數(shù)返回的結(jié)果的類型不一定于id對(duì)應(yīng)的列的類型相符,更安全的方式可以采用string來(lái)轉(zhuǎn)型 fina long max = ( () )。 聚合函數(shù)也可以作為被查詢的一個(gè)屬性返回。 // 返回所有的訂單的生產(chǎn)廠商和他們的訂單價(jià)值總額 final Query query = ( select , sum() FROM Order o group by )。)。 和SQL一樣,如果聚合函數(shù)不是select...from的唯一一個(gè)返回列,需要使用GROUP BY語(yǔ)句。GROUP BY應(yīng)該包含select語(yǔ)句中除了聚合函數(shù)外的所有屬性。 // 返回所有的訂單的生產(chǎn)廠商的的名字,貨物號(hào)碼和每種貨物的訂單價(jià)值總額 // 注意group final Query query = ( select , , sum() FROM Order o group by ,)。 如果還需要加上查詢條件,需要使用HAVING條件語(yǔ)句而不是WHERE語(yǔ)句。 // 返回所有的訂單的生產(chǎn)廠商是foo的貨物號(hào)碼和每種貨物的訂單價(jià)值總額 // 這里having = 39。foo39。為條件 final Query query = ( select , , sum() FROM Order o group by , having =39。foo39。)。 在HAVING語(yǔ)句里可以跟WHERE語(yǔ)句一樣使用參數(shù)。 // 返回所有的訂單的生產(chǎn)廠商是foo的貨物號(hào)碼和每種貨物的訂單價(jià)值總額 // 這里having = 39。foo39。為條件 final Query query = ( select , , sum() FROM Order o group by , having =?1)。 ( 1, foo )。 final List result = ()。 關(guān)聯(lián)(join)在JPQL中,大部分的情況下,使用對(duì)象屬性都隱含了關(guān)聯(lián)(join)。例如在以下查詢中: final Query query = ( select o from Order o where =2000 order by )。 當(dāng)這個(gè)句JPQL編譯成以下的SQL時(shí)就會(huì)自動(dòng)包含了關(guān)聯(lián),JPQL編譯成SQL時(shí)關(guān)聯(lián)默認(rèn)取左關(guān)聯(lián)(left join)。 select , , , , , from orderTable as o left join addressTable where = 2000 但在一些情況下,我們?nèi)匀恍枰獙?duì)關(guān)聯(lián)做精確的控制。因此JPQL仍然支持和SQL中類似的關(guān)聯(lián)語(yǔ)法: left out join/left join inner join left join/inner join fetch left join, left out join等義,都是允許符合條件的右邊表達(dá)式中的Entiies為空。 // 返回所有地址為2000的Order紀(jì)錄,不管Order中是否有OrderItem final Query query = ( select o from Order o left join where =2000 order by )。 由于JPQL默認(rèn)采用left join。這樣的查詢和以下的JPQL其實(shí)是等價(jià)的。 // 返回所有地址為2000的Order紀(jì)錄,不管Order中是否有OrderItem final Query query = ( select o from Order o where =2000 order by )。 需要顯式使用left join/left outer join的情況會(huì)比較少。inner join要求右邊的表達(dá)式必須返回Entities。 // 返回所有地址為2000的Order紀(jì)錄,Order中必須有OrderItem final Query query = ( select o from Order o inner join where =2000 order by )。 left/left out/inner join fetch提供了一種靈活的查詢加載方式來(lái)提高查詢的性能。在默認(rèn)查詢中,Entity中的集合屬性默認(rèn)不會(huì)被關(guān)聯(lián),集合屬性默認(rèn)是緩加載( lazyload )。 // 默認(rèn)JPQL編譯后不關(guān)聯(lián)集合屬性變量(orderItems)對(duì)應(yīng)的表 final Query query = ( select o from Order o inner join where =2000 order by )。 final List result = ()。 // 這時(shí)獲得Order實(shí)體中orderItems( 集合屬性變量 )為空 final Order order = (Order)( 0 ) // 當(dāng)應(yīng)用需要時(shí),EJB3 Runtime才會(huì)執(zhí)行一條SQL語(yǔ)句來(lái)加載屬于當(dāng)前Order的OrderItems Collection orderItems = ()。 這樣的查詢性能上有不足的地方。為了查詢N個(gè)Order,我們需要一條SQL語(yǔ)句獲得所有的Order的原始/對(duì)象屬性, 但需要另外N條語(yǔ)句獲得每個(gè)Order的orderItems集合屬性。為了避免N+1的性能問(wèn)題,我們可以利用join fetch一次過(guò)用一條SQL語(yǔ)句把Order的所有信息查詢出來(lái)。 // 返回所有地址為2000的Order紀(jì)錄,Order中必須有OrderItem final Query query = ( select o from Order o inner join fetch where =2000 order by )。由于使用了fetch,這個(gè)查詢只會(huì)產(chǎn)生一條SQL語(yǔ)句,比原來(lái)需要N+1條SQL語(yǔ)句在性能上有了極大的提升。在查詢中使用參數(shù)查詢時(shí),參數(shù)類型除了String, 原始數(shù)據(jù)類型( int, double等)和它們的對(duì)象類型( Integer, Double等),也可以是Entity的實(shí)例。 final Query query = ( select o from Order o where = ?1 order by )。 final Address address = new Address( 2001, foo street, foo city, foo province )。 // 直接把a(bǔ)ddress對(duì)象作為參數(shù)。 ( 1, address )。 批量更新(Batch Update)JPQL支持批量更新。 Query query = (update Order as o set =:newvender, =39。fooPart39。 where = 39。foo39。)。 (newvender, barVender)。 // update的記錄數(shù) int result = ()。 (Batch Remove)JPQL支持批量刪除。 Query query = (DELETE FROM Order)。 int result = ()。 Query query = (DELETE FROM Order AS o WHERE =39。redsoft39。)。 int result = ()。