Need help with Hibernate? Read this first:
http://www.hibernate.org/ForumMailingli ... AskForHelp
Hibernate version:
3.0.3
Name and version of the database you are using:
Oracle 10g
App Server
JBoss 3.2.7
I am seeing a problem in our application with OutOfMemoryException. According to the heap dump, I have 131 SessionFactoryImpl objects all owned by SessionFactoryObjectFactory. I was quite surprised to see this as our code only creates the SessionFactory once within a static initializer block. I was hoping that person someone could help point me in the right direction to find the source of the problem.
We use a web filter to implement the Open Session in View pattern. Below is the code of the filter.
Code:
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
try {
chain.doFilter(request, response);
HibernateUtil.commitTransaction();
} finally {
HibernateUtil.closeSession();
}
}
And the HibernateUtil class:
Code:
public class HibernateUtil {
private static final Logger LOGGER = Logger.getLogger(HibernateUtil.class);
private static final LogHelper LOG_HELPER = LogHelper.getInstance();
private static Configuration configuration;
private static SessionFactory sessionFactory;
private static final ThreadLocal threadSession = new ThreadLocal();
private static final ThreadLocal threadTransaction = new ThreadLocal();
private static final ThreadLocal threadInterceptor = new ThreadLocal();
// Create the initial SessionFactory from the default configuration files
static {
try {
configuration = new Configuration();
sessionFactory = configuration.configure().buildSessionFactory();
} catch (Throwable ex) {
LOGGER.error("Building SessionFactory failed.", ex);
throw new ExceptionInInitializerError(ex);
}
}
/**
* Returns the SessionFactory used for this static class.
*
* @return SessionFactory
*/
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
/**
* Returns the original Hibernate configuration.
*
* @return Configuration
*/
private static Configuration getConfiguration() {
return configuration;
}
/**
* Retrieves the current Session local to the thread.
* <p/>
* If no Session is open, opens a new Session for the running thread.
*
* @return Session
*/
public static Session getSession()
throws InfrastructureException {
Session s = (Session) threadSession.get();
try {
if (s == null) {
LOGGER.debug("Opening new Session for this thread.");
if (getInterceptor() != null) {
LOGGER.debug("Using interceptor: " + getInterceptor().getClass());
s = getSessionFactory().openSession(getInterceptor());
} else {
s = getSessionFactory().openSession();
}
threadSession.set(s);
}
} catch (HibernateException ex) {
LOG_HELPER.errorStackTrace(ex, LOGGER) ;
throw new InfrastructureException(ex);
}
return s;
}
/**
* Closes the Session local to the thread.
*/
public static void closeSession()
throws InfrastructureException {
try {
Session s = (Session) threadSession.get();
threadSession.set(null);
if (s != null && s.isOpen()) {
LOGGER.debug("Closing Session of this thread.");
s.close();
}
} catch (HibernateException ex) {
LOG_HELPER.errorStackTrace(ex, LOGGER) ;
throw new InfrastructureException(ex);
}
}
/**
* Start a new database transaction.
*/
public static void beginTransaction()
throws InfrastructureException {
Transaction tx = (Transaction) threadTransaction.get();
try {
if (tx == null) {
LOGGER.debug("Starting new database transaction in this thread.");
tx = getSession().beginTransaction();
threadTransaction.set(tx);
}
} catch (HibernateException ex) {
LOG_HELPER.errorStackTrace(ex, LOGGER) ;
throw new InfrastructureException(ex);
}
}
/**
* Commit the database transaction.
*/
public static void commitTransaction()
throws InfrastructureException {
Transaction tx = (Transaction) threadTransaction.get();
try {
if ( tx != null && !tx.wasCommitted()
&& !tx.wasRolledBack() ) {
LOGGER.debug("Committing database transaction of this thread.");
tx.commit();
}
threadTransaction.set(null);
} catch (HibernateException ex) {
rollbackTransaction();
LOG_HELPER.errorStackTrace(ex, LOGGER) ;
throw new InfrastructureException(ex);
}
}
/**
* Commit the database transaction.
*/
public static void rollbackTransaction()
throws InfrastructureException {
Transaction tx = (Transaction) threadTransaction.get();
try {
threadTransaction.set(null);
if ( tx != null && !tx.wasCommitted() && !tx.wasRolledBack() ) {
LOGGER.debug("Tyring to rollback database transaction of this thread.");
tx.rollback();
}
} catch (HibernateException ex) {
LOG_HELPER.errorStackTrace(ex, LOGGER) ;
throw new InfrastructureException(ex);
} finally {
closeSession();
}
}
/**
* Register a Hibernate interceptor with the current thread.
* <p>
* Every Session opened is opened with this interceptor after
* registration. Has no effect if the current Session of the
* thread is already open, effective on next close()/getSession().
*/
public static void registerInterceptor(final Interceptor interceptor) {
threadInterceptor.set(interceptor);
}
private static Interceptor getInterceptor() {
Interceptor interceptor =
(Interceptor) threadInterceptor.get();
return interceptor;
}
}
Any ideas on why I have so many SessionFactoryImpl instances?