繁体   English   中英

Hibernate或JPA中的“ SELECT COUNT(*)FROM(SELECT DISTINCT…)”

[英]`SELECT COUNT(*) FROM (SELECT DISTINCT …)` in Hibernate or JPA

对于Hibernate或JPA来说,这似乎是一个琐碎的用例,但是我已经努力了几天,才能使它正常工作。

我有一个position实体类,其中包含latitudelongitudeupdateTime字段(以及其他字段)。 我想计算这三个字段的不同组合的数量,而忽略其他字段。 在SQL中,这很简单:

SELECT COUNT(*) FROM (SELECT DISTINCT LONGITUDE, LATITUDE, UPDATE_TIME FROM POSITION) AS TEMP;

从应用程序的其余部分抽象myh数据库实现很重要,因为不同的用户可能希望使用不同的数据库引擎。 (哎呀,我使用h2进行测试,并使用mariadb进行本地生产...)

我一直在尝试使用Hibernate或JPA语法将此SQL转换为Java代码,但我不知道该怎么做。

编辑-这是我使用JPA所能获得的效果(参考: https : //en.wikibooks.org/wiki/Java_Persistence/Criteria

public long getCountDistinctInFlightPositions() {
    Session session = sessionFactory.openSession();

    CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();

    CriteriaQuery<Tuple> innerQuery = criteriaBuilder.createTupleQuery();
    Root<Position> position = innerQuery.from(Position.class);
    innerQuery.multiselect(
        position.get("longitude"),
        position.get("latitude"),
        position.get("updateTime")
    );

    // The method countDistinct(Expression<?>) in the type CriteriaBuilder is not applicable for the arguments (CriteriaQuery<Tuple>)

    criteriaBuilder.countDistinct(innerQuery);

    return 1;
}

您可以这样操作:

CriteriaQuery<Long> countQuery = cb.createQuery( Long.class );
Root<Position> root = countQuery.from( Position.class );

countQuery.select( cb.count( root.get( "id" ) ) );

Subquery<Integer> subQuery = countQuery.subquery( Integer.class );
Root<Position> subRoot = subQuery.from( Position.class );
subQuery.select( cb.min( subRoot.get( "id" ) ) );
subQuery.groupBy( subRoot.get( "longitude" ), 
  subRoot.get( "latitude" ), 
  subRoot.get( "updateTime" ) );

countQuery.where( root.get( "id" ).in( subQuery ) );

Long count = entityManager.createQuery( countQuery ).getSingleResult();

这有效地生成以下SQL:

SELECT COUNT( p0.id ) FROM Position p0
 WHERE p0.id IN (
   SELECT MIN( p1.id )
     FROM Position p1
    GROUP BY p1.longitude, p1.latitude, p1.updateTime )

在我有3行并且其中2行具有相同的经度,纬度和更新时间元组的情况下,查询将返回结果2。

确保在此处[Longtitude,Latitude,UpdateTime]上保持良好的索引,以便可以利用更快的GROUP BY执行优势。 PK已经被b树索引了,所以其他操作COUNT / MIN应该已经由该索引轻松地进行了解释。

暂无
暂无

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

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