如果提供限制和偏移量,则queryDSL返回一条记录

时间:2017-03-15 14:05:10

标签: java jpa querydsl

我正在使用queryDSL JPA。

我正在尝试以块的形式加载数据,因此我使用.offset().limit() 我正在查询'single_entry'表,其中包含10000条记录。

我使用以下函数来查询数据

private Collection<SingleEntry> getSingleEntries(FiscalPeriod fp, Predicate filter, Integer offset, Integer limit) {
    BooleanExpression initialFilter = getSingleEntriesFilter(fp);
    return query.selectFrom(QSingleEntry.singleEntry).where(initialFilter.and(filter)).offset(offset).limit(limit).fetch();
}

private BooleanExpression getSingleEntriesFilter(FiscalPeriod fp) {
    int period = fp.getPeriod();
    int year = fp.getYear();
    QSingleEntryModification sem = QSingleEntryModification.singleEntryModification;
    QSingleEntry se = QSingleEntry.singleEntry;

    BooleanExpression fiscalPeriodMatches = se.year.eq(year).and(se.period.loe(period));
    //excludes single entries that moved from this period
    BooleanExpression excludeMoved = se.documentNumber.notIn(query.selectDistinct(sem.documentNumber).from(sem)
            .where(sem.moved.eq(true)
                    .and(sem.originYear.eq(year)
                            .and(sem.originPeriod.loe(period)).and(sem.movedToPeriod.gt(period).or(sem.movedToYear.ne(year))))));
    BooleanExpression movedToPeriodOrNonMoved = se.documentNumber.in(query.selectDistinct(sem.documentNumber).from(sem)
            .where(sem.moved.eq(false).and(sem.originYear.eq(year).and(sem.originPeriod.loe(period))).or(sem.movedToPeriod.loe(period).and(sem.movedToYear.eq(year)))));
    return fiscalPeriodMatches.and(excludeMoved).or(movedToPeriodOrNonMoved);
}

当offset等于0且设置了limit时,Hibernate会产生以下查询:

select
   * //replaced with * to be concise
from
    single_entry singleentr0_ 
where
    (
        singleentr0_.year=? 
        and singleentr0_.period<=? 
        and (
            singleentr0_.document_number not in  (
                select
                    distinct TOP(?) singleentr1_.document_number 
                from
                    single_entry_modification singleentr1_ 
                where
                    singleentr1_.moved=? 
                    and singleentr1_.origin_year=? 
                    and singleentr1_.origin_period<=? 
                    and (
                        singleentr1_.moved_to_period>? 
                        or singleentr1_.moved_to_year<>?
                    )
            )
        ) 
        or singleentr0_.document_number in (
            select
                distinct singleentr2_.document_number 
            from
                single_entry_modification singleentr2_ 
            where
                singleentr2_.moved=? 
                and singleentr2_.origin_year=? 
                and singleentr2_.origin_period<=? 
                or singleentr2_.moved_to_period<=? 
                and singleentr2_.moved_to_year=?
        )
    ) 
    and singleentr0_.account_number=?

此查询返回一个结果,但是,如果我在数据库管理器中运行此查询,则返回正确数量的结果。

如果偏移量非零并且设置了限制,则Hibernate会生成以下查询:

WITH query AS (SELECT
    inner_query.*,
    ROW_NUMBER() OVER (
ORDER BY
    CURRENT_TIMESTAMP) as __hibernate_row_nr__ 
FROM
    ( select
        * //replaced with * to be concise
    from
        single_entry singleentr0_ 
    where
        (singleentr0_.year=? 
        and singleentr0_.period<=? 
        and (singleentr0_.document_number not in  (select
            distinct singleentr1_.document_number 
        from
            single_entry_modification singleentr1_ 
        where
            singleentr1_.moved=? 
            and singleentr1_.origin_year=? 
            and singleentr1_.origin_period<=? 
            and (singleentr1_.moved_to_period>? 
            or singleentr1_.moved_to_year<>?))) 
        or singleentr0_.document_number in (select
            distinct singleentr2_.document_number 
        from
            single_entry_modification singleentr2_ 
        where
            singleentr2_.moved=? 
            and singleentr2_.origin_year=? 
            and singleentr2_.origin_period<=? 
            or singleentr2_.moved_to_period<=? 
            and singleentr2_.moved_to_year=?)) 
        and singleentr0_.account_number=? ) inner_query ) SELECT
            * //replaced with * to be concise
        FROM
            query 
        WHERE
            __hibernate_row_nr__ >= ? 
            AND __hibernate_row_nr__ < ?

该查询返回正确的结果数。

我有两个问题: 1.为什么第一个查询只返回1个结果? 2.为什么在第一个查询中TOP(?)不会出现在顶级选择中而是出现在子查询中?

如果要提供其他源代码,请与我们联系 谢谢!

0 个答案:

没有答案