繁体   English   中英

Spring Data JPA 规范 groupBy

[英]Spring Data JPA Specification groupBy

首先对不起我的英语。

我想使用 jpa 进行分组,例如:从数据流组中按脚本、dstip 选择脚本、灰尘、计数(*)。 所以,写这些代码:

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();
            }
        };
    }
}

但是,SQL日志是:休眠:

select
    count(dataflow0_.id) as col_0_0_ 
from
    Dataflow dataflow0_

休眠:

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 ?

那么,如何解决呢? 谢谢!

您可以通过specification实现spring数据group by ,只需按照
对于 2.0 之前或之后的版本,请参阅第 2.6 节第 3.6 节 对于单个存储库操作,两个版本具有相同的解决方案。 对于 *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;
}

存储库:

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

片段存储库及其实现:

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))
        );
    }
}

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

对于仍在寻找如何在 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;
}

规范不支持 groupBy。 SimpleJpaRepository 替换 query.select/multiselect 由 query.select(root)

暂无
暂无

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

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