我正在使用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(?)不会出现在顶级选择中而是出现在子查询中?
如果要提供其他源代码,请与我们联系 谢谢!