Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ResultSet holdability into the View layer broken by Hibernate 5 #26557

Closed
symposion opened this issue Feb 17, 2021 · 2 comments
Closed

ResultSet holdability into the View layer broken by Hibernate 5 #26557

symposion opened this issue Feb 17, 2021 · 2 comments
Assignees
Labels
in: data Issues in data modules (jdbc, orm, oxm, tx) status: backported An issue that has been backported to maintenance branches type: documentation A documentation task
Milestone

Comments

@symposion
Copy link

symposion commented Feb 17, 2021

Some time ago a fix was introduced for this: #16954 . It allows specifying that ResultSets should be held open beyond transaction commit. (Separate problem: there's no easy way to do this for JPATransactionManager, which makes usage with Spring Data hard). In the meantime, however, changes made in Hibernate 5 have re-broken this functionality. Hibernate now aggressively closes all JDBC resources on transaction commit, and the Hibernate maintainers have basically said that cursor holdability is evil and they're not interested in supporting it (https://discourse.hibernate.org/t/resultset-holdability-not-working-with-hibernate/1445/9)

As things stand, this makes it pretty much impossible (AFAICT) to build a fully streaming stack from database to MVC layer (using Open Session In View) - in particular a streaming REST API that returns a stream of JSON objects from a large dataset. It also renders HibernateTransactionManager.allowResultSetAccessAfterCompletion pointless because Hibernate closes the result set anyway, irrespective of the behaviour of the underlying JDBC driver.

It's not clear to me if there's a viable solution for any of this, but as a minimum it would be great if this was clearly documented as a limitation. I've spent hours wandering through issues, forum posts + SO answers getting conflicting information about this and it would be good to have a definitive statement of what is and isn't possible in this regard

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Feb 17, 2021
@jhoeller jhoeller self-assigned this Feb 17, 2021
@jhoeller jhoeller added in: data Issues in data modules (jdbc, orm, oxm, tx) type: documentation A documentation task and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Feb 17, 2021
@jhoeller jhoeller added this to the 5.3.5 milestone Feb 17, 2021
@jhoeller jhoeller modified the milestones: 5.3.5, 5.3.6 Mar 15, 2021
@jhoeller jhoeller modified the milestones: 5.3.6, 5.3.7 Apr 12, 2021
@jhoeller jhoeller modified the milestones: 5.3.7, 5.3.8 May 5, 2021
@jhoeller jhoeller modified the milestones: 5.3.8, 5.3.9 Jun 4, 2021
@jhoeller jhoeller modified the milestones: 5.3.9, 5.3.10 Jul 7, 2021
@jhoeller jhoeller modified the milestones: 5.3.10, 5.x Backlog Sep 13, 2021
@nicklyra
Copy link

nicklyra commented Oct 27, 2021

I've run into this very problem today when some code started exhibiting java.sql.SQLException: Operation not allowed after ResultSet closed errors during serialization. A method annotated with @RequestMapping is returning an entity that contains a database entity that has some lazy-loaded fields, and it looks as though the transaction is closed at some point before AbstractJackson2HttpMessageConverter.writeInternal gets called, and our Hibernate5Module has Hibernate5Module.Feature.FORCE_LAZY_LOADING enabled.

It looks like it is then trying to lazy-load those fields, but it can't because the transaction (and thus the connection and its result set) is already closed.

This may sound naive as I don't know a great deal about Spring Boot internals, but if a @RestController is annotated with @Transactional could the transaction/session closure merely be delayed until after object serialization was complete? It might be a little ugly and break down the separation between Controller and View of course... seems you'd likely need the VIew to issue a callback when it was done doing what it needed to do so the Controller side of things could clean up.

I guess one potential workaround would be to grab the ObjectMapper and serialize the object graph first, but of course this wouldn't work well for very large object graphs.

Update: I discovered that in our case it wasn't what I thought it was: there was some wrongful interplay between a custom Hibernate Persister and a service into which it called that was annotated with @Transactional. This was causing a new transaction to start while Hibernate and the Persister were processing the ResultSet internally. In our case it appears that the right / expected thing was actually happening with serialization, though I'm actually a little bit surprised that it works. Leaving this comment here just in case it helps someone else who is researching similar behavior in the future.

@jhoeller jhoeller modified the milestones: 6.x Backlog, 6.0.11 Jul 11, 2023
@jhoeller
Copy link
Contributor

jhoeller commented Jul 11, 2023

Reading up on the current state of affairs, it seems appropriate to deprecate setAllowResultAccessAfterCompletion since there is no chance of this getting addressed in the Hibernate 5.x line, and to document it as effectively not working as intended anymore. Also, Spring only supports Hibernate 6.x via JPA which does not have an equivalent setting to begin with, so deprecation is also applicable in that direction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: data Issues in data modules (jdbc, orm, oxm, tx) status: backported An issue that has been backported to maintenance branches type: documentation A documentation task
Projects
None yet
Development

No branches or pull requests

4 participants