using group by with specification in Spring data count method

天大地大妈咪最大 提交于 2019-12-13 10:29:40

问题


I want to implement a spring data method which check result of the following query

select count(1) from installation_requested_t requested 
where requested.installation_id in 
      (select installation_id from installation_requested_t where request_id=?) 
group by requested.installation_id
having count(1)>1;

For the project, it is mandatory to use specification with the spring data jpa. So there is my repository method call :

installationRequestedRepository.count(
                               InstallationSpecs
                               .existsInstallationRequestLinkedToAnotherEPR(movingEprId)
);

and my spec method:

public static Specification<InstallationRequested> existsInstallationRequestLinkedToAnotherEPR(final Long EPRId) {
    return new Specification<InstallationRequested>() {

        @Override
        public Predicate toPredicate(Root<InstallationRequested> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

            Subquery<Long> InstallationIdsLinkedToEPRsubquery = query.subquery(Long.class);

            InstallationIdsLinkedToEPRsubquery.select(root.get(InstallationRequested_.id))
                    .where(cb.equal(root.get(InstallationRequested_.environmentPermitRequestId), EPRId));

            Subquery<InstallationRequested> installationRequestForTheseInstallationIdsWhoAreLinkedToAnotherEPR =
                    query.subquery(InstallationRequested.class);

            installationRequestForTheseInstallationIdsWhoAreLinkedToAnotherEPR
                    .select(installationRequestForTheseInstallationIdsWhoAreLinkedToAnotherEPR
                            .from(InstallationRequested.class))
                    .where(root.get(InstallationRequested_.id).in(InstallationIdsLinkedToEPRsubquery))
                    .groupBy(root.get(InstallationRequested_.id))
                    .having(cb.greaterThan(cb.count(cb.literal(1)), cb.literal(1l)));

            return cb.exists(installationRequestForTheseInstallationIdsWhoAreLinkedToAnotherEPR);

        }
    };

}

And my problem is that everything doesn't execute well:

org.springframework.dao.InvalidDataAccessApiUsageException: 
org.hibernate.hql.internal.ast.QuerySyntaxException: 
unexpected token: where near line 1, column 333 
[select count(generatedAlias0) from be.question.domain.model.request.installation.InstallationRequested as generatedAlias0 
where exists 
    (select generatedAlias1 from be.question.domain.model.request.installation.InstallationRequested as generatedAlias1 
    where generatedAlias0.id in 
        (select generatedAlias0.id from  where generatedAlias0.environmentPermitRequestId=1072487L) 
    group by generatedAlias0.id having count(1)>1L)
]; 

Do you have an idea to make my spec work and another way to make the asked task ?


回答1:


I found a solution to my problem. I fix the specification:

public static Specification<InstallationRequested> existsInstallationRequestLinkedToAnotherEPR(final Long EPRId) {
    return new Specification<InstallationRequested>() {

        @Override
        public Predicate toPredicate(Root<InstallationRequested> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

            // subquery to select installation ids
            Subquery<Long> InstallationIdsLinkedToEPRsubquery = query.subquery(Long.class);
            Root<InstallationRequested> selectIdSubQueryRoot =
                    InstallationIdsLinkedToEPRsubquery.from(InstallationRequested.class);
            InstallationIdsLinkedToEPRsubquery
                    .select(selectIdSubQueryRoot.get(InstallationRequested_.installation).get(Installation_.id))
                    .where(cb.equal(selectIdSubQueryRoot.get(InstallationRequested_.environmentPermitRequestId),
                            EPRId));

            // subquery to select count of installation request group by installation id
            Subquery<Long> installationRequestForTheseInstallationIdsWhoAreLinkedToAnotherEPR =
                    query.subquery(Long.class);
            Root<InstallationRequested> groupBySubQueryRoot =
                    installationRequestForTheseInstallationIdsWhoAreLinkedToAnotherEPR
                            .from(InstallationRequested.class);
            Path<Long> installationIdInGroupBySubQuery =
                    groupBySubQueryRoot.get(InstallationRequested_.installation).get(Installation_.id);

            installationRequestForTheseInstallationIdsWhoAreLinkedToAnotherEPR.select(cb.count(cb.literal(1)))
                    .where(installationIdInGroupBySubQuery.in(InstallationIdsLinkedToEPRsubquery))
                    .groupBy(installationIdInGroupBySubQuery)
                    .having(cb.greaterThan(cb.count(cb.literal(1)), cb.literal(1l)));

            // returning existing condition on result of the group by
            return cb.exists(installationRequestForTheseInstallationIdsWhoAreLinkedToAnotherEPR);

        }
    };

}

By the way, if someone as a better idea i would be happy to read it ;)



来源:https://stackoverflow.com/questions/49007656/using-group-by-with-specification-in-spring-data-count-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!