[
https://hibernate.onjira.com/browse/HHH-4808?page=com.atlassian.jira.plug...
]
Martin Rexa commented on HHH-4808:
----------------------------------
I've tried suggested fix of method SessionImpl.initializeCollection() but it
didn't help, connection stays bound to the session (in heap dump I can see path from
JDBC connection to collection loaded lazily (proxy class?)).
The workaround I found is calling session.disconnect() before calling BlockingCache.get(),
which fixed my problem. I found quite interesting that right after calling
session.disconnect() I tried to call session.isConnected() and it was returning true,
although I was not able to reproduce the deadlock in the test which was creating it always
when I didn't call session.disconnect().
In general I think this bug should be solved since it can hurt quite a lot, using any kind
of synchronization might cause deadlock under higher load (especially after flushing
cache) since all threads holding JDBC connection might be waiting for resource locked by
thread which badly needs JDBC connection to finish it's task and unlock.
SessionImpl.initializeCollection() does not release JDBC connection
(if outside of a transaction)
-------------------------------------------------------------------------------------------------
Key: HHH-4808
URL:
https://hibernate.onjira.com/browse/HHH-4808
Project: Hibernate ORM
Issue Type: Bug
Components: core
Affects Versions: 3.2.7, 3.3.2
Reporter: Martin Renner
Priority: Critical
Attachments: Test.java
With {{ConnectionReleaseMode.AFTER_TRANSACTION}} (the default), Hibernate does not
release the JDBC connection when resolving a lazily loaded collection, if this happens
*outside* of an active transaction.
First, I will describe, what happens if Hibernate executes a query outside of a
transaction. Then I will describe how lazy collection loading behaves differently.
When the method {{list}} of a query ({{QueryImpl.java}}) is getting called, Hibernate
delegates to {{SessionImpl.list()}}. After having loaded the list, {{SessionImpl.list()}}
calls {{SessionImpl.afterOperation()}}, which calls
{{jdbcContext.afterNontransactionalQuery()}} (as there is no active transaction). This
leads to {{ConnectionManager.afterTransaction()}} which releases the JDBC connection. This
is exactly what I expect to happen.
Now to the lazily loaded collection:
{{Hibernate.initialize(collection)}} and {{person.getPets().size()}} both end up in
{{SessionImpl.initializeCollection()}}. This call gets dispatched down to
{{Loader.doQueryAndInitializeNonLazyCollections()}} and {{Loader.doQuery()}}. The
important fact is, that {{ConnectionManager.afterTransaction()}} never gets called (like
in the query-example above).
The result is, that the JDBC connection is not released.
IMHO resolving of a lazily loaded collection should behave like executing a query.
{{SessionImpl.initializeCollection()}} should call {{SessionImpl.afterOperation()}} in the
same way as {{SessionImpl.list()}} is doing this.
I will attach a small demo application which shows the difference (concerning
{{ConnectionManager}}) between queries and collections.
--
This message is automatically generated by JIRA.
For more information on JIRA, see:
http://www.atlassian.com/software/jira