秋天的北京一如既往的沒太陽,分不清天上是雲是霧或者又是什麼奇奇怪怪的東西,建築物不分黑白的證實着本身的輪廓。霧濛濛的天一眼望不到邊,就像我須要用到Spring Data Jpa 實現一個特別小的SQL,怎麼寫都看不到我想要的效果同樣。html
想實現的SQL十分簡單,就是一個簡單的統計:spring
SELECT activity_code, activity_name, sum(contact_user_nums), conversion_step_code, conversion_step FROM epm_estimate_main WHERE activity_code ='1' GROUP BY conversion_step_code ORDER BY contact_user_nums DESC;
因爲一些條條框框的緣由,最終選擇用jpa的這種實現方式,想到這個玩意五分鐘寫完就能回家玩遊戲,因而上來就寫:api
可是查詢出來的結果卻不是很好看:第一,我沒有拿到想要的求和;第二,查詢出來的結果集包括全部字段;
好在分組和排序都按照預期的想法實現了。ui
首先去B某搜索引擎上找,找來找去,你們的方法無非四種:
第一種:去XXX的JPA, MyBatis真香;
第二種:實在不行用JPQL;
第三種:本身建立CriteriaBuilder,CriteriaQuery及Root;
第四種:不知道怎麼寫,等大腿。搜索引擎
國內搜完,因而又去G某引擎上翻翻,老外彷佛問的比較具體,但都沒找到我想要的答案(散裝的四級仍是吃力);spa
翻看了一些網上的問題與解答,貌似出現了一個規律,用findAll方法實現Specification接口的文章彷佛都有這個問題,而使用EntityManager本身來實現的小夥伴都不怎麼關注。code
赤裸裸的歧視,下定決心就要用這個findAll實現一把。htm
窗外的天色愈來愈暗,可是我以爲這麼簡單的一個查詢竟然浪費了我開黑的時間,不禁得開始懷疑本身。無論我怎麼對CriteriaQuery.multiselect操做,查詢出來得結果集都是包含全部字段,不禁得開始懷疑multiselect這個方法爲何沒有生效,JpaSpecificationExecutor這個接口到底什麼居心?blog
找到這個接口的API:有兩個實現類(其中QuerydslJpaRepository已顯示過時)
排序
剩下的這個實現類SimpleJpaRepository中找到對應的findAll方法,它調用了本類中的其餘方法,一路向下找,最終在方法調用的末端,找到了其中的貓膩:
我在multiselect方法中的全部定義都被 query.select(root)
覆蓋掉了!
天色已晚,華燈初上,最後原本想重寫一下這個方法,但撇了一眼樓下的公交站,廣告牌的背景彷佛有點過年的味道。
那段代碼最終變成這樣(Spring Boot自動註冊了EntityManager):
CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery<EstimateDO> query = builder.createQuery(EstimateDO.class); Root<EstimateDO> root = query.from(EstimateDO.class); query .multiselect( root.get("activityCode"), root.get("activityName"), builder.sum(root.get("contactUserNums").as(Long.class)).alias("contactUserNums"), root.get("conversionStepCode"), root.get("conversionStep") ); List<Predicate> predicates = new ArrayList(); predicates.add( builder.equal(root.get("activityCode").as(String.class), estimateDO.getActivityCode()) ); if (!StringUtils.isEmpty(estimateDO.getContactCode())) { predicates.add( builder.equal(root.get("contactCode").as(String.class), estimateDO.getContactCode()) ); } query .where(predicates.toArray(new Predicate[predicates.size()])) .groupBy(root.get("conversionStepCode")) .orderBy(builder.desc(root.get("contactUserNums"))); List<EstimateDO> list = entityManager.createQuery(query).getResultList();
個人決心一文不值。