爲何Jpa中Specification的求和sum不生效

秋天的北京一如既往的沒太陽,分不清天上是雲是霧或者又是什麼奇奇怪怪的東西,建築物不分黑白的證實着本身的輪廓。霧濛濛的天一眼望不到邊,就像我須要用到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

image.png

可是查詢出來的結果卻不是很好看:第一,我沒有拿到想要的求和;第二,查詢出來的結果集包括全部字段;
好在分組和排序都按照預期的想法實現了。ui

首先去B某搜索引擎上找,找來找去,你們的方法無非四種:
第一種:去XXX的JPA, MyBatis真香;
第二種:實在不行用JPQL;
第三種:本身建立CriteriaBuilder,CriteriaQuery及Root;
第四種:不知道怎麼寫,等大腿。搜索引擎

國內搜完,因而又去G某引擎上翻翻,老外彷佛問的比較具體,但都沒找到我想要的答案(散裝的四級仍是吃力);spa

翻看了一些網上的問題與解答,貌似出現了一個規律,用findAll方法實現Specification接口的文章彷佛都有這個問題,而使用EntityManager本身來實現的小夥伴都不怎麼關注。code

赤裸裸的歧視,下定決心就要用這個findAll實現一把。htm

窗外的天色愈來愈暗,可是我以爲這麼簡單的一個查詢竟然浪費了我開黑的時間,不禁得開始懷疑本身。無論我怎麼對CriteriaQuery.multiselect操做,查詢出來得結果集都是包含全部字段,不禁得開始懷疑multiselect這個方法爲何沒有生效,JpaSpecificationExecutor這個接口到底什麼居心?blog

找到這個接口的API:有兩個實現類(其中QuerydslJpaRepository已顯示過時)
image.png排序

剩下的這個實現類SimpleJpaRepository中找到對應的findAll方法,它調用了本類中的其餘方法,一路向下找,最終在方法調用的末端,找到了其中的貓膩:
image.png

我在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();

個人決心一文不值。

相關文章
相關標籤/搜索