秋天的北京一如既往的没太阳,分不清天上是云是雾或者又是什么奇奇怪怪的东西,建筑物不分黑白的证实着本身的轮廓。雾蒙蒙的天一眼望不到边,就像我须要用到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();
个人决心一文不值。