Hibernate ThreadLocal Session management compatible with ForkJoinPool?
I usually use the Hibernate ThreadLocal session management pattern in Java web projects:
The Thread Local Session pattern makes use of the java.lang.ThreadLocal class to create a Session that is accessible from a single application thread. This is particularly convenient in multithreaded applications, such as web applications.
In projects I implement this with
<property name="current_session_context_class">thread</property>
in the hibernate.xml
and using SessionFactory.getCurrentSession()
to get a session whenever I need one.
Now I have a program that is not a Servlet, but does heavy parallel computing and database interaction.
I want to implement this with a ForkJoinPool. Now I wonder whether it is a mistake to use Hibernate ThreadLocal session management in this scenario. As far as I understand, a ForkJoinPool uses a smaller number of threads and shares them among running tasks while other tasks are sleeping. (Motivated by stalling/annoying " task in transaction' connections,) I want to close() every Hibernate Session after a unit of work.
So.. when I call HibernateSessionFactory.getThreadLocalSession().close() at the end of my Task - and the Task is run in a ForkJoinPool - will troubles arise? Should I drop the ThreadLocal pattern for heavy parallel calculations and manage the Sessions myself?
Thanks in advance for any answers.
Using ThreadLocalSessionContext
could be problematic for you, but it depends on what your tasks are doing.
A ForkJoinPool
(javadocs) is meant for use in cases where tasks spawn other tasks (the fork), and wait for them to complete (the join). While waiting, the Thread that was executing the parent task may be re-used to execute a child task. According to the javadocs for ThreadLocalSessionContext, the Session
gets closed when you commit a transaction you get from it (ie there's only ever one transaction per Session
).
So, if you have a 'parent' task that calls sessionFactory.getCurrentSession()
, and does some stuff, then calls commit(), the Session gets closed and there's no danger of inappropriate interaction.
However, if you spawn children tasks AFTER calling .getCurrentSession()
and BEFORE calling .commit()
, you may run in to issues because other tasks may execute on this Thread, and .getCurrentSession()
would return the session used by the parent task. This is almost certainly not what you want, because the children tasks should presumably be doing the same thing as each other, and you wouldn't want one arbitrarily sharing Session
state with the parent while others don't.
So in summary, you should:
session.close()
if you get the Session
from .getCurrentSession()
, because it's the responsibility of the CurrentSessionContext
to deal with that. .commit()
before spawning children tasks. As a footnote, I found this wiki page to be a helpful read on the subject as well.
链接地址: http://www.djcxy.com/p/58650.html