Skip to content

HibernateJpaDialect does not allow ConnectionManager to eagerly release Connection for long-running Session [SPR-6895] #11560

@spring-projects-issues

Description

@spring-projects-issues

Christopher G. Stach II opened SPR-6895 and commented

When JpaTransactionManager gets a handle for the Hibernate session's connection in doBegin with

ConnectionHandle conHandle = getJpaDialect().getJdbcConnection(em, definition.isReadOnly());

it never actually lets go. JpaTransactionManager eventually calls

getJpaDialect().releaseJdbcConnection(txObject.getConnectionHolder().getConnectionHandle(),
					txObject.getEntityManagerHolder().getEntityManager());

in doCleanupAfterCompletion, but HibernateJpaDialect has no implementation for releaseJdbcConnection.

Because this borrowed connection handle is never released, o.h.jdbc.ConnectionManager never returns the connection to the pool.

This setup eventually turns into a connection leak with Spring Web Flow when Hibernate fetches more connections to instantiate lazy collections and such, but the connection handles in the pool never get closed. Even if your database times out the connections and your pool eventually figures that out, the handles are still out of the pool until then.

After turning on debug logging for o.h.jdbc.ConnectionManager, things look like this:

$ grep jdbc.ConnectionManager debug.log | cut -c22- | sort | uniq -c
1 c.ConnectionManager.getConnection(ConnectionManager.java:167)
1 c.ConnectionManager.openConnection(ConnectionManager.java:446)
160 DEBUG jdbc.ConnectionManager aggressively releasing JDBC connection
157 DEBUG jdbc.ConnectionManager opening JDBC connection
156 DEBUG jdbc.ConnectionManager releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
1 DEBUG jdbc.ConnectionManager skipping aggresive-release due to borrowed connection

156 + 1 skipped release (and the two lines from the stack trace when the connection times out in the connection pool) = 157 opens.

$ grep jdbc.ConnectionManager debug.log | cut -c22- | sort | uniq -c
3 c.ConnectionManager.getConnection(ConnectionManager.java:167)
3 c.ConnectionManager.openConnection(ConnectionManager.java:446)
256 DEBUG jdbc.ConnectionManager aggressively releasing JDBC connection
251 DEBUG jdbc.ConnectionManager opening JDBC connection
248 DEBUG jdbc.ConnectionManager releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
3 DEBUG jdbc.ConnectionManager skipping aggresive-release due to borrowed connection

Again, 248 + 3 = 251.

Now, I don't see a need to have this JDBC connection even associated with the transaction as I do everything through JPA. I may be wrong about that, but it seems to only be used in this one spot. I went ahead and subclassed HibernateJpaDialect and made getJdbcConnection return null, just like DefaultJpaDialect. Things seem to be working, also (two separate runs):

$ grep jdbc.ConnectionManager debug.log | cut -c22- | sort | uniq -c
99 DEBUG jdbc.ConnectionManager aggressively releasing JDBC connection
95 DEBUG jdbc.ConnectionManager opening JDBC connection
95 DEBUG jdbc.ConnectionManager releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]

$ grep jdbc.ConnectionManager debug.log | cut -c22- | sort | uniq -c
165 DEBUG jdbc.ConnectionManager aggressively releasing JDBC connection
161 DEBUG jdbc.ConnectionManager opening JDBC connection
161 DEBUG jdbc.ConnectionManager releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]

The numbers match up and I am no longer getting timed out connections in the pool, which means I also shouldn't be running out of connections.

This should probably either be fixed, or this whole JDBC connection transaction association should be optional.

This was also described at http://ksevindik.blogspot.com/2008_11_01_archive.html.


Affects: 3.0 GA, 3.0.1

Issue Links:

Referenced from: commits ef227c5

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions