[
https://hibernate.onjira.com/browse/HHH-4808?page=com.atlassian.jira.plug...
]
Martin Rexa commented on HHH-4808:
----------------------------------
This issue is a big problem for using net.sf.ehcache.constructs.blocking.BlockingCache in
hibernate since it can cause a deadlock if the amount of threads is much higher then the
maximum size of connection pool.
Scenario leading to the deadlock:
Thread 1 comes to BlockingCache.get and gets a lock for particular key. This thread must
reach BlockingCache.put, otherwise particular key stays locked and will block other
threads trying to get the same key. Before calling BlockingCache.put the thread must
construct the value which requires DB connection. Other threads are doing their job and at
some point they reach BlockingCache.get for the same key which Thread 1 is trying to
construct and are stopped by the lock. But because of this bug it could be that last DB
operation they did was lazy loading and therefore these threads are holding DB connection.
If the amount of these threads becomes the same as the maximum size of connection pool, we
have a deadlock, since Thread 1 will never get connection needed to unblock other threads
holding it.
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