Skip to content

Commit 60ad64b

Browse files
committed
update explanation of limit/fetch join problem for H6
1 parent e79d7ef commit 60ad64b

File tree

2 files changed

+35
-9
lines changed

2 files changed

+35
-9
lines changed

documentation/src/main/asciidoc/userguide/chapters/query/hql/QueryLanguage.adoc

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2105,17 +2105,17 @@ include::{sourcedir}/HQLTest.java[tags=hql-limit-example]
21052105
----
21062106
====
21072107
2108-
These are well-defined limits: the number of results returned by `getMaxResults()` will be limited to 50, as promised.
2108+
These are well-defined limits: the number of results returned by the database will be limited to 50, as promised.
21092109
But not every query is quite so well-behaved.
21102110
21112111
[NOTE]
21122112
====
21132113
_Limiting_ certainly _isn't_ a well-defined relational operation, and must be used with care.
21142114

2115-
A limit can easily break the semantics of certain other features of HQL, including <<hql-explicit-fetch-join,fetch joins>>.
2115+
In particular, limits don't play well with <<hql-explicit-fetch-join,fetch joins>>.
21162116
====
21172117
2118-
This next query is accepted by HQL, but the last `Phone` in the result list might have an incomplete collection of phones:
2118+
This next query is accepted by HQL, and no more than 50 results are returned by `getResultList()`, just as expected:
21192119
21202120
[[hql-bad-limit-example]]
21212121
//.Order by example
@@ -2126,7 +2126,36 @@ include::{sourcedir}/HQLTest.java[tags=hql-bad-limit-example]
21262126
----
21272127
====
21282128
2129-
The `limit 50` here refers to the total number of rows returned from the database.
2130-
The final number of ``Phone``s returned by `getResultList()` will be fewer, after Hibernate eliminates duplicate ``Phone``s from the result list.
2129+
However, if you log the SQL executed by Hibernate, you'll notice something wrong:
2130+
2131+
[source, SQL, indent=0]
2132+
----
2133+
select
2134+
p1_0.id,
2135+
c1_0.phone_id,
2136+
c1_0.calls_ORDER,
2137+
c1_0.id,
2138+
c1_0.duration,
2139+
c1_0.payment_id,
2140+
c1_0.call_timestamp,
2141+
p1_0.phone_number,
2142+
p1_0.person_id,
2143+
p1_0.phone_type
2144+
from
2145+
Phone p1_0
2146+
join
2147+
phone_call c1_0
2148+
on p1_0.id=c1_0.phone_id
2149+
order by 1
2150+
----
2151+
2152+
What happened to the `limit` clause?
2153+
2154+
[IMPORTANT]
2155+
====
2156+
When limits or pagination are combined with `fetch join`, Hibernate must retrieve all matching results from the database and _apply the limit in memory_!
2157+
2158+
This _almost certainly_ isn't the behavior you were hoping for, and in general will exhibit _terrible_ performance characteristics.
2159+
====
21312160
21322161
In the next chapter we'll see a completely different way to write queries in Hibernate.

documentation/src/test/java/org/hibernate/userguide/hql/HQLTest.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2939,15 +2939,12 @@ public void test_hql_bad_limit_example() {
29392939

29402940
doInJPA(this::entityManagerFactory, entityManager -> {
29412941
//tag::hql-bad-limit-example[]
2942-
// don't do this!
2942+
// don't do this! join fetch should not be used with limit
29432943
List<Phone> wrongCalls = entityManager.createQuery(
29442944
"select p " +
29452945
"from Phone p " +
2946-
// join fetch should not be used with limit
29472946
"join fetch p.calls " +
2948-
// but if you insist, at least sort by the collection owner
29492947
"order by p " +
2950-
// this won't be the final number of results!
29512948
"limit 50",
29522949
Phone.class)
29532950
.getResultList();

0 commit comments

Comments
 (0)