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
getResultListfrom JPA and return aResponsewith the list as the body. AMessageBodyWriterwill 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
getResultStreamfrom JPA and return aResponsewith the stream as the body. AMessageBodyWriterwill take care of serializing the stream to JSON. Unfortunately this doesn't work because it seems theEntityManageris closed after the JAX-RS method has been executed and before theMessageBodyWriteris invoked. This means that the underlyingResultSetis also closed and the writer cannot read from the stream any more. - Use a
StreamingOutputasResponsebody. 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.
