简体   繁体   English

Spring Data JPA 规范 groupBy

[英]Spring Data JPA Specification groupBy

sorry for my english first.首先对不起我的英语。

i want use jpa to groupby, like : select scrip, dustup, count(*) from data flow group by scrip, dstip.我想使用 jpa 进行分组,例如:从数据流组中按脚本、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:但是,SQL日志是:休眠:

select
    count(dataflow0_.id) as col_0_0_ 
from
    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_ 
from
    Dataflow dataflow0_ limit ?

so, how to resolve it?那么,如何解决呢? thanks!谢谢!

You can achieve spring data group by by specification , just follow您可以通过specification实现spring数据group by ,只需按照
section 2.6 or section 3.6 for version before or after 2.0.对于 2.0 之前或之后的版本,请参阅第 2.6 节第 3.6 节 For single repository manipulation, the two versions have identical solution.对于单个存储库操作,两个版本具有相同的解决方案。 For the *all * repository solution, before 2.0 use customized factory bean , while after 2.0 this factory bean manipulation is omitted.对于 *all * 存储库解决方案,在 2.0 之前使用定制的工厂 bean ,而在 2.0 之后,此工厂 bean 操作被省略。

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. one-for-all-repository 和 one-for-single-repository 的主要区别在于,在 one-for-single-repository 的情况下,它可以访问真实的实体类,如 spring 参考文档中的User 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.这样你就不需要使用泛型类型来引用任何类型的实体,而在 one-for-all-repository 的情况下,自定义方法的实现使用泛型类型,它的类信息可以(或必须)是从注入的JpaEntityInformation获得,如第 3.6 节所述。

For people still looking for how to apply "group by" in Spring jpa Specification, you can use something like the following snippet:对于仍在寻找如何在 Spring jpa 规范中应用“group by”的人,您可以使用类似以下代码段的内容:


...
private Dataflow dataflowFilter;

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

Specification doesn't support groupBy.规范不支持 groupBy。 SimpleJpaRepository replaced query.select/multiselect by query.select(root) SimpleJpaRepository 替换 query.select/multiselect 由 query.select(root)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM