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

JDBC Connection to reset not identical to originally prepared Connection with Hibernate 5.2 [SPR-14393] #18966

Closed
spring-projects-issues opened this issue Jun 23, 2016 · 13 comments
Assignees
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

@spring-projects-issues spring-projects-issues commented Jun 23, 2016

Koen van Dijk opened SPR-14393 and commented

This issue occured after updating my application to the latest versions of spring, spring data and hibernate (from 4.3.9.Final to 5.2.0.Final, 4.2.2.Release to 4.3.0.Release, 1.9.1.RELEASE to 1.10.2.Release)

I noticed that a warning started to appear in my logs. " WARN org.springframework.orm.jpa.vendor.HibernateJpaDialect (HibernateJpaDialect.java:366) qtp883841715-95 :JDBC Connection to reset not identical to originally prepared Connection - please make sure to use connection release mode ON_CLOSE (the default) and to run against Hibernate 4.2+ (or switch HibernateJpaDialect's prepareConnection flag to false"

I found this warning quite worrisome since it indicated a fairly serious bug in my application if it were true that the connection that initiated the transaction was not the same as the one that ended it. After some digging I found that the connections were in fact equal and that this warning was caused by the fact that Hikari uses proxy objects to wrap the connections. Hikari did manage to wrap the same connection but it uses a different wrapper object during the beginning and ending of the transaction.

The piece of code in the class org.springframework.orm.jpa.vendor.HibernateJpaDialect of particular interest is:

if (conToReset != this.preparedCon)
 {
	LogFactory.getLog(HibernateJpaDialect.class).warn(
	"JDBC Connection to reset not identical to originally prepared Connection - please " +
	"make sure to use connection release mode ON_CLOSE (the default) and to run against " +
	"Hibernate 4.2+ (or switch HibernateJpaDialect's prepareConnection flag to false");
}

I have the following question:
I am under the impression that in this case I am safely able to ignore this warning since it is only the proxy object that differs and not the actual jdbc connection, do you share my conclusion?


Affects: 4.3 GA

Reference URL: https://github.com/brettwooldridge/HikariCP

Issue Links:

  • #18899 Support for Hibernate ORM 5.2
  • #17860 HibernateJpaDialect should warn about connection release mode other than ON_CLOSE (when upgrading from 4.0.x)
  • #19116 Default connection release mode inconsistent with Hibernate 5.1.1

Referenced from: commits 5e08598, 351a729, 711eb99

0 votes, 6 watchers

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Jun 23, 2016

Juergen Hoeller commented

Indeed, you may safely ignore the warning in this case. However, we should try to avoid the warning in the first place here...

So if Hikari provides different wrappers to the same native connection, are they all equal according to .equals? Or is there any other way to find out that they're alright for our purposes?

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Jun 23, 2016

Koen van Dijk commented

I had a look at the equals method and it actually defaults to the Object's default method. So not much help there. Unfortunately the wrapperclass com.zaxxer.hikari.pool.HikariProxyConnection.java is not a subclass of java.reflection.Proxy but their custom implementation of the proxy pattern.

The proxy object inherits <T> T unwrap(Class<T> iface) from com.zaxxer.hikari.pool.ProxyConnection. Which seems to return the wrapped connection object. I guess it is posible to use this, but this will only work for Hikari's Proxy Implementation. So I am not sure if that is something you would want to do.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Jun 23, 2016

Juergen Hoeller commented

Actually, I wonder why there is a different Hikari handle involved in the first place... Is Hibernate 5.2 not using ON_CLOSE by default anymore but rather some policy where it reobtains a handle to the same physical connection during a transaction?

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Jun 23, 2016

Juergen Hoeller commented

We can also check for equality of connection handles as well as equality of unwrapped connection handles. unwrap is a standard JDBC 4.0 method, after all.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Jun 23, 2016

Juergen Hoeller commented

This is available in the latest 4.3.1.BUILD-SNAPSHOT now... Would be great if you could give it an early try!

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Jun 24, 2016

Koen van Dijk commented

I actually wonder of ON_CLOSE is used at all in hibernate. I got this from the most recent (5.2) javadoc of the ConnectionReleaseMode. Seems like this release mode has been done away with a long time ago.

ON_CLOSE
Indicates that connections should only be released when the Session is explicitly closed or disconnected; this is the legacy (Hibernate2 and pre-3.1) behavior.

ConnectionReleaseMode.java

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Jun 24, 2016

Koen van Dijk commented

I tried it out and unfortunately the warning still appears. Upon closer inspection it seems that the Connection used for this transaction has already been released back to the connection Pool.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Jun 24, 2016

Juergen Hoeller commented

Alright, thanks for trying it. Indeed, it seems that the root of the problem is the connection release mode: Hibernate 5.2 introduces a new PhysicalConnectionHandlingMode configuration model there, with the default effectively being after-transaction release now... where it was effectively on-close before for non-JTA transactions. I'll try to fix it at that level, adapting the default in our HibernateJpaVendorAdapter.

BTW, this whole reset-after-prepare step is only necessary for the read-only flag and for custom isolation levels per transaction. If you use neither, we're not even trying to reset, so you won't see a warning either. Switching off the prepareConnection flag on HibernateJpaDialect has the same effect, i.e. not passing the read-only flag to the underlying JDBC connection.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Jun 24, 2016

Juergen Hoeller commented

Manually setting Hibernate 5.2's "hibernate.connection.handling_mode" property to "DELAYED_ACQUISITION_AND_HOLD" should to the job. Could you give that a try? We would simply do that by default as of Spring 4.3.1 then.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Jun 24, 2016

Koen van Dijk commented

Seems to work perfectly, with both the 4.3.0.RELEASE and the 4.3.1.BUILD-SNAPSHOT.

Thanks for the tip.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Jun 24, 2016

Juergen Hoeller commented

Both HibernateJpaVendorAdapter and LocalSessionFactoryBuilder enforce Hibernate 5.2's connection handling mode DELAYED_ACQUISITION_AND_HOLD now. In the former case, only when prepareConnection=true (the default); in the latter case, only when not using JTA, which approximates the default behavior against older Hibernate versions.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Jul 31, 2016

Manuel Dominguez Sarmiento commented

We're using LocalSessionFactoryBuilder and when upgrading from [Hibernate 5.1.0 + Spring 4.2.5] to [Hibernate 5.2.1 + Spring 4.3.2] the effective connection release mode changed from "after transaction" to "on close". The Hibernate default for non-JTA environments has been "after transaction" for ages, since "on close" holds connections way too long. This caused major connection pool exhaustion which went unnoticed in our preproduction and test environments, but was hit immediately once our apps got real production load.

The defaults should be:
"after transaction" for non-JTA environments
"after statement" for JTA environments
At least this is what connection release mode "auto" (the default) has been doing in Hibernate for a long time.

Otherwise upgrading to latest Spring+Hibernate versions causes a major change in behavior and performance.
This can be resolved by explicitly configuring the following Hibernate property:

hibernate.connection.handling_mode=DELAYED_ACQUISITION_AND_RELEASE_AFTER_TRANSACTION
(see org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode which is new in Hibernate 5.2 - this used to be handled by the old hibernate.connection.release_mode property)

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Jul 31, 2016

Manuel Dominguez Sarmiento commented

FYI "on close" ceased to be the default back in 2005:
https://hibernate.atlassian.net/browse/HHH-1038

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants