我可以在一个Spring Data JPA存储库方法上使用带有规范的聚合函数执行@Query吗?

时间:2015-10-20 20:35:35

标签: hibernate jpa spring-data-jpa

我与previously asked 问题非常相似。 除了在我的情况下查询即将找到多个sum()

public interface IQuotaRepository extends JpaRepository<QuotaDao, Long>, JpaSpecificationExecutor<QuotaDao> {

        @Query( "select new ca.quota.kpi.model.dto.TotalDto(sum(q.value1), sum(q.value2), sum(q.value3), sum(q.value4), "
                                                                + "sum(q.value5), sum(q.value6), sum(q.value7), sum(q.value8), "
                                                                + "sum(q.value9), sum(q.value10), sum(q.value11), sum(q.value12)) from QuotaDao q")
        public TotalDto sumQuota();//Specification<QuotaDao> spec

        @Query( "select new ca.quota.kpi.model.dto.TotalDto(sum(q.value1), sum(q.value2), sum(q.value3), sum(q.value4), "
                                                                + "sum(q.value5), sum(q.value6), sum(q.value7), sum(q.value8), "
                                                                + "sum(q.value9), sum(q.value10), sum(q.value11), sum(q.value12)) from QuotaDao q")
        public TotalDto sumQuotaWithSpec(Specification<QuotaDao> spec);
}
  • sumQuota()工作正常
  • sumQuotaWithSpec(规范规范)抛出一个 QueryParameterException:超出声明的ordinal参数数量的位置。请记住,序数参数是基于1的!职位:1

我希望重用&#34;规范规范&#34;使用来自网格控件的各种参数来过滤结果。

请您建议任何解决方案或替代方案

1 个答案:

答案 0 :(得分:0)

唉... 我发现解决方案可能比严格的JPA方法更具有解决方法

首先我在存储库接口中声明了方法

public interface IQuotaRepositoryCustom{

    public TotalDto sumQuotaWithFilters(FilterParameterExtJs6[] filters);
    ...
}

然后在存储库实现中实现此方法

@Repository
public class IQuotaRepositoryImpl implements IQuotaRepositoryCustom {
    private static Logger logger = Logger.getLogger(IQuotaRepositoryImpl.class);    
    private final String SELECT_COUNT_FOR_TOTAL = "select count(*)";
    private final String SELECT_COUNT_FOR_TOTAL_QUOTA = SELECT_COUNT_FOR_TOTAL + " from QuotaDao q";
    private final String SELECT_TOTAL = "select new org.avp.quota.kpi.model.dto.TotalDto(sum(q.value1), sum(q.value2), sum(q.value3), sum(q.value4), "
                                                                                    + "sum(q.value5), sum(q.value6), sum(q.value7), sum(q.value8), "
                                                                                    + "sum(q.value9), sum(q.value10), sum(q.value11), sum(q.value12))";

private final String SELECT_TOTAL_QUOTA = SELECT_TOTAL + " from QuotaDao q";
    ...
    public TotalDto sumQuotaWithFilters(FilterParameterExtJs6[] filters) {
        String countHql = SELECT_COUNT_FOR_TOTAL_QUOTA + buildWhereClause(filters);
        Query countQuery = em.createQuery(countHql.toString());
        Long count = (Long)countQuery.getSingleResult();
        if(count.longValue() == 0L)
            return new TotalDto();
        String hql = SELECT_TOTAL_QUOTA+ buildWhereClause(filters);
        Query query = em.createQuery(hql.toString());
        return (TotalDto) query.getSingleResult();
    }
}

TotalDto是普通的数据传输对象

    public class TotalDto {

        private long value1;
        private long value2;
        private long value3;
        private long value4;
        private long value5;
        private long value6;
        private long value7;
        private long value8;
        private long value9;
        private long value10;
        private long value11;
        private long value12;
        private long total;
// constructor and getters/setters removed
}

本地帮助函数名称建议只构建where子句字符串(由于来自UI的非常具体的格式,我不发布代码)

private String buildWhereClause(FilterParameterExtJs6[] filterParameters) {
    StringBuffer sb = new StringBuffer();
    // Build where clause string 
    return sb.toString();
}

最后在服务中调用此存储库方法

public TotalDto getFilteredSummAggregateQuota(final FilterParameterExtJs6[] filterParameters){
    TotalDto aggregateTotalQuota = quotaRepository.sumQuotaWithFilters(filterParameters);
    return aggregateTotalQuota;
}

希望这会帮助你解决问题。