添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

sorry for my english first.

i want use jpa to groupby, like : select scrip, dustup, count(*) from data flow group by scrip, dstip. so, write these code:

public class DataflowSpec {
    public static Specification<Dataflow> search(final String[] group, final String[] sort, final String[] desc) {
        return new Specification<Dataflow>() {
            @Override
            public Predicate toPredicate(Root<Dataflow> root1, CriteriaQuery<?> query1, CriteriaBuilder builder) {
                // TODO Auto-generated method stub
                CriteriaQuery<Tuple> query = builder.createQuery(Tuple.class);
                Root<Dataflow> root = query.from(Dataflow.class);
                query.multiselect(root.get("srcip"), root.get("dstip"), builder.count(root));
                query.groupBy(root.get("srcip"), root.get("dstip"));
                query.orderBy(builder.desc(root.get("srcip").as(BigInteger.class)));
                return query.getRestriction();

but , SQL log is: Hibernate:

select
    count(dataflow0_.id) as col_0_0_ 
    Dataflow dataflow0_

Hibernate:

select
    dataflow0_.id as id1_2_,
    dataflow0_.byteall as byteall2_2_,
    dataflow0_.bytedn as bytedn3_2_,
    dataflow0_.byteup as byteup4_2_,
    dataflow0_.dstip as dstip5_2_,
    dataflow0_.dstport as dstport6_2_,
    dataflow0_.engieid as engieid7_2_,
    dataflow0_.flag as flag8_2_,
    dataflow0_.netid as netid9_2_,
    dataflow0_.pkgall as pkgall10_2_,
    dataflow0_.pkgdn as pkgdn11_2_,
    dataflow0_.pkgup as pkgup12_2_,
    dataflow0_.protocolid as protoco17_2_,
    dataflow0_.rtt as rtt13_2_,
    dataflow0_.srcip as srcip14_2_,
    dataflow0_.srcport as srcport15_2_,
    dataflow0_.updatetime as updatet16_2_ 
    Dataflow dataflow0_ limit ?

so, how to resolve it? thanks!

so you return the Predicate for the WHERE clause (to somewhere) ... and what happens to the SELECT clause part? – Neil Stockton Apr 2, 2016 at 7:55

For people still looking for how to apply "group by" in Spring jpa Specification, you can use something like the following snippet:

private Dataflow dataflowFilter; @Override public Predicate toPredicate(Root&ltDataflow&gt root, CriteriaQuery&lt?&gt cq, CriteriaBuilder cb) { Predicate predicate = cb.conjunction(); predicate.getExpressions().add(cb.equal(root.get("id"), dataflowFilter.getId())); cq.groupBy(root.get("id")); return predicate;

You can achieve spring data group by by specification, just follow
[section 2.6][1] or [section 3.6][2] for version before or after 2.0. For single repository manipulation, the two versions have identical solution. For the *all * repository solution, before 2.0 use [customized factory bean][3], while after 2.0 this factory bean manipulation is omitted.

public Map<AlarmMsg.AlarmLevel, Long> testSpecification(String neId) {
    SingularAttribute attribute = AlarmData_.isClear;
    Specification<Object> where = Specification.where(
        (root, query, cb) -> cb.equal(root.get(attribute), false)
    final Map<AlarmMsg.AlarmLevel, Long> result = alarmDataRepository.groupAndCount(AlarmData_.alarmLevel, where );
    return result;

repository:

public interface AlarmDataRepository extends JpaRepository<AlarmData, Long>, JpaSpecificationExecutor<AlarmData>, CustomizedGroupCountRepository {

Fragment repository and its implementation:

public interface CustomizedGroupCountRepository {
    Map<AlarmMsg.AlarmLevel, Long> groupAndCount(SingularAttribute singularAttribute, Specification where);
public class CustomizedGroupCountRepositoryImpl implements CustomizedGroupCountRepository {
    private final EntityManager entityManager;
    public CustomizedGroupCountRepositoryImpl(EntityManager entityManager) {
        Assert.notNull(entityManager, "EntityManager must not be null!");
        this.entityManager = entityManager;
    @Override
    public Map<AlarmMsg.AlarmLevel, Long> groupAndCount(SingularAttribute singularAttribute, Specification where) {
        final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        final CriteriaQuery<Tuple> query = criteriaBuilder.createQuery(Tuple.class);
        final Root<AlarmData> root = query.from(AlarmData.class);
        final Path<AlarmMsg.AlarmLevel> expression = root.get(singularAttribute);
        query.multiselect(expression, criteriaBuilder.count(root));
        query.select(criteriaBuilder.tuple(expression, criteriaBuilder.count(root)));
        query.where(where.toPredicate(root, query, criteriaBuilder));
        query.groupBy(expression);
        final List<Tuple> resultList = entityManager.createQuery(query).getResultList();
        return resultList.stream()
            .collect(toMap(
                t -> t.get(0, AlarmMsg.AlarmLevel.class),
                t -> t.get(1, Long.class))

The main difference between one-for-all-repository and one-for-single-repository is, in one-for-single-repository case, it can access the real entity class, like User in spring reference document. So that you don't need to use generic types to refer an any-typed entity, while in one-for-all-repository case, the implementation of the customized method uses generic types, and its class information could (or must) be gained from an injected JpaEntityInformation as stated in both section 3.6. [1]: https://docs.spring.io/spring-data/jpa/docs/1.8.0.RELEASE/reference/html/#repositories.single-repository-behaviour [2]: https://docs.spring.io/spring-data/jpa/docs/2.0.5.RELEASE/reference/html/#repositories.single-repository-behavior [3]: https://jeroenbellen.com/spring-data-extending-the-jpa-specification-executor/

'query.multiselect(expression, criteriaBuilder.count(root));' 'query.select(criteriaBuilder.tuple(expression, criteriaBuilder.count(root)));' Why these two lines, when just one would suffice? – shivarajan May 21, 2022 at 0:13

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.