I'm implementing a GET
method in Quarkus that should send large amounts of data to the client. The data is read from the database using JPA/Hibernate, serialized to JSON, and then sent to the client. How can this can be done efficiently without having the whole data in memory? I tried the following three possibilities all without success:
- Use
getResultList
from JPA and return aResponse
with the list as the body. AMessageBodyWriter
will take care of serializing the list to JSON. However, this will pull all data into memory which is not feasible for a larger number of records. - Use
getResultStream
from JPA and return aResponse
with the stream as the body. AMessageBodyWriter
will take care of serializing the stream to JSON. Unfortunately this doesn't work because it seems theEntityManager
is closed after the JAX-RS method has been executed and before theMessageBodyWriter
is invoked. This means that the underlyingResultSet
is also closed and the writer cannot read from the stream any more. - Use a
StreamingOutput
asResponse
body. The same problem as in 2. occurs.
So my question is: what's the trick for sending large data read via JPA with Quarkus?
CodePudding user response:
Here you have some resources that can help you with this:
- Using reactive Hibernate: https://quarkusio.zulipchat.com/#narrow/stream/187030-users/topic/Large.20datasets.20using.20reactive.20SQL.20clients
- Paging vs Forward only ResultSets: https://knes1.github.io/blog/2015/2015-10-19-streaming-mysql-results-using-java8-streams-and-spring-data.html
The last article is for SpringBoot, but the idea can also be implemented with Quarkus.
CodePudding user response:
Do your results have to be all in one response? How about making the client request the next results page until there's no next - a typical REST API pagination exercise? Also the JPA backend will only fetch that page from the database so there's no moment when everything would sit in memory.