So I have built a query in Java with QueryDsl like the following (production names swapped for dummy names, but query is 1:1 the same).
QTestA qTestA = QTestA.testA;
QTestB qTestB = QTestB.testB;
QTestC qTestC = QTestC.testC;
JPAQuery<OutputFormat> base = queryFactory
.select(Projections.constructor(OutputFormat.class, qTestB.somefield, qTestB.somefield2, qTestB.somefield3, qTestC.someBfield))
.from(qTestA, qTestB, qTestC)
.where(qTestA.someparam.eq("1234"))
.where(qTestA.bid.eq(qTestB.id))
.where(qTestA.cid.eq(qTestC.id));
When I run this I get the following error:
java.lang.OutOfMemoryError: Java heap space
at oracle.jdbc.driver.DynamicByteArray.getStringFromUTF8(DynamicByteArray.java:1067)
at oracle.jdbc.driver.DynamicByteArray.getString(DynamicByteArray.java:634)
// ...
at com.querydsl.jpa.impl.AbstractJPAQuery.getResultList(AbstractJPAQuery.java:160)
at com.querydsl.jpa.impl.AbstractJPAQuery.fetch(AbstractJPAQuery.java:202)
When I build the same statement as with QueryDsl in normal SQL, I get 240k results. Is this too much? Or is there an error in my QueryDsl query?
If this is in fact a memory leak, then I'd suspect the Oracle JDBC driver first, as its the source of String allocation in your stack trace.
240K results is a lot of records to return. With the four fields being projected here we're talking about one million objects minimally. If these Strings are large, then this is a problem. Not really related to QueryDSL though. If you would create the same amount and size of Strings in a loop, you'd get the same exception.
For queries that have this many results you want to use QueryDSL's iterate()
method. This result set iterator is backed by a scrollable result and prevents all records to be in memory at the same time, as it allows previous records to be garbage collected during iteration.