Hibernate is giving Session is closed exception
I am using Hibenate along with Struts 1.3 I am getting an error "org.hibernate.SessionException: Session is closed".
Here is the HibernateUtil:
private static Logger log = Logger.getLogger(HibernateUtil.class);
private static Configuration configuration;
private static SessionFactory sessionFactory;
@SuppressWarnings("unchecked")
private static final ThreadLocal threadSession = new ThreadLocal();
@SuppressWarnings("unchecked")
private static final ThreadLocal threadTransaction = new ThreadLocal();
@SuppressWarnings("unchecked")
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();
// We could also let Hibernate bind it to JNDI:
// configuration.configure().buildSessionFactory()
} catch (Throwable ex) {
// We have to catch Throwable, otherwise we will miss
// NoClassDefFoundError and other subclasses of Error
log.error("Building SessionFactory failed.", ex);
throw new ExceptionInInitializerError(ex);
}
}
/**
* Returns the SessionFactory used for this static class.
*
* @return SessionFactory
*/
public static SessionFactory getSessionFactory() {
/* Instead of a static variable, use JNDI:
SessionFactory sessions = null;
try {
Context ctx = new InitialContext();
String jndiName = "java:hibernate/HibernateFactory";
sessions = (SessionFactory)ctx.lookup(jndiName);
} catch (NamingException ex) {
throw new BFSException(ex);
}
return sessions;
*/
return sessionFactory;
}
/**
* Returns the original Hibernate configuration.
*
* @return Configuration
*/
public static Configuration getConfiguration() {
return configuration;
}
/**
* Rebuild the SessionFactory with the static Configuration.
*
*/
public static void rebuildSessionFactory()
throws QnsAndAnsException {
synchronized(sessionFactory) {
try {
sessionFactory = getConfiguration().buildSessionFactory();
} catch (Exception ex) {
throw new QnsAndAnsException(ex);
}
}
}
/**
* Rebuild the SessionFactory with the given Hibernate Configuration.
*
* @param cfg
*/
public static void rebuildSessionFactory(Configuration cfg)
throws QnsAndAnsException {
synchronized(sessionFactory) {
try {
sessionFactory = cfg.buildSessionFactory();
configuration = cfg;
} catch (Exception ex) {
throw new QnsAndAnsException(ex.getMessage());
}
}
}
/**
* Retrieves the current Session local to the thread.
* <p/>
* If no Session is open, opens a new Session for the running thread.
*
* @return Session
*/
@SuppressWarnings("unchecked")
public static Session getSession()
throws QnsAndAnsException {
Session s = (Session) threadSession.get();
try {
if (s == null || s.isOpen() == false) {
log.debug("Opening new Session for this thread.");
if (getInterceptor() != null) {
//log.debug("Using interceptor: " + getInterceptor().getClass());
s = getSessionFactory().openSession(getInterceptor());
} else {
s = getSessionFactory().openSession();
}
threadSession.set(s);
}
} catch (HibernateException ex) {
throw new QnsAndAnsException(ex.getMessage());
}
return s;
}
/**
* Closes the Session local to the thread.
*/
@SuppressWarnings("unchecked")
public static void closeSession()
throws QnsAndAnsException {
try {
Session s = (Session) threadSession.get();
threadSession.set(null);
if (s != null && s.isOpen()) {
log.debug("Closing Session of this thread.");
s.close();
}
} catch (HibernateException ex) {
throw new QnsAndAnsException(ex.getMessage());
}
}
/**
* Start a new database transaction.
*/
@SuppressWarnings("unchecked")
public static void beginTransaction()
throws QnsAndAnsException {
Transaction tx = (Transaction) threadTransaction.get();
try {
if (tx == null) {
log.debug("Starting new database transaction in this thread.");
tx = getSession().beginTransaction();
threadTransaction.set(tx);
}
} catch (HibernateException ex) {
//ex.printStackTrace();
throw new QnsAndAnsException(ex.getMessage());
}
}
/**
* Commit the database transaction.
*/
@SuppressWarnings("unchecked")
public static void commitTransaction()
throws QnsAndAnsException {
Transaction tx = (Transaction) threadTransaction.get();
try {
if ( tx != null && !tx.wasCommitted()
&& !tx.wasRolledBack() ) {
log.debug("Committing database transaction of this thread.");
tx.commit();
}
threadTransaction.set(null);
} catch (HibernateException ex) {
ex.printStackTrace();
rollbackTransaction();
throw new QnsAndAnsException(ex.getMessage());
}
}
/**
* Rollback the database transaction.
*/
@SuppressWarnings("unchecked")
public static void rollbackTransaction()
throws QnsAndAnsException {
Transaction tx = (Transaction) threadTransaction.get();
try {
threadTransaction.set(null);
if ( tx != null && !tx.wasCommitted() && !tx.wasRolledBack() ) {
log.debug("Tyring to rollback database transaction of this thread.");
tx.rollback();
}
} catch (HibernateException ex) {
throw new QnsAndAnsException(ex.getMessage());
} finally {
closeSession();
}
}
/**
* 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 Connection getConnection()
throws QnsAndAnsException {
Session s = (Session) threadSession.get();
try {
if (s == null) {
//log.debug("Opening new Session for this thread.");
if (getInterceptor() != null) {
//log.debug("Using interceptor: " + getInterceptor().getClass());
s = getSessionFactory().openSession(getInterceptor());
} else {
s = getSessionFactory().openSession();
}
threadSession.set(s);
Connection conn = s.connection();
conn.setAutoCommit(false);
}
} catch (HibernateException ex) {
throw new QnsAndAnsException(ex.getMessage());
} catch (SQLException e) {
throw new QnsAndAnsException(e.getMessage());
}
return null;
}*/
/**
* Reconnects a Hibernate Session to the current Thread.
*
* @param session The Hibernate Session to be reconnected.
*/
@SuppressWarnings("unchecked")
public static void reconnect(Session session)
throws QnsAndAnsException {
try {
session.reconnect();
threadSession.set(session);
} catch (HibernateException ex) {
throw new QnsAndAnsException(ex.getMessage());
}
}
/**
* Disconnect and return Session from current Thread.
*
* @return Session the disconnected Session
*/
@SuppressWarnings("unchecked")
public static Session disconnectSession()
throws QnsAndAnsException {
Session session = getSession();
try {
threadSession.set(null);
if (session.isConnected() && session.isOpen())
session.disconnect();
} catch (HibernateException ex) {
throw new QnsAndAnsException(ex);
}
return session;
}
/**
* 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().
*/
@SuppressWarnings("unchecked")
public static void registerInterceptor(Interceptor interceptor) {
threadInterceptor.set(interceptor);
}
private static Interceptor getInterceptor() {
Interceptor interceptor =
(Interceptor) threadInterceptor.get();
return interceptor;
}
here is the XML file:
<!-- property name="connection.datasource">java:/MySqlDS</property -->
<property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
<property name="transaction.auto_close_session">false</property>
<property name="hibernate.transaction.flush_before_completion">true</property>
<!-- property name="transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</property -->
<!-- Because of 'Y' and 'N' being used for boolean types -->
<property name="query.substitutions">true='Y', false='N'</property>
<property name="query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</property>
<property name="default_schema">qnsandans</property>
<property name="hibernate.dbcp.timeBetweenEvictionRunsMillis">120000</property>
<property name="hibernate.dbcp.numTestsPerEvictionRun">-1</property>
<property name="hibernate.dbcp.minEvictableIdleTimeMillis">120000</property>
<!-- configuration pool via c3p0 -->
<property name="c3p0.acquire_increment">1</property>
<property name="c3p0.idle_test_period">100</property>
<property name="c3p0.max_size">15</property>
<property name="c3p0.max_statements">0</property>
<property name="c3p0.min_size">1</property>
<property name="c3p0.timeout">180</property> <!-- seconds -->
<!-- JD开发者_StackOverflow社区BC connection pool (use the built-in) -->
<property name="hibernate.connection.release_mode">after_transaction</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="hibernate.current_session_context_class">org.hibernate.context.ThreadLocalSessionContext</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">false</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">create</property>
And here is the DAO class I am using:
connection = super.getConnection();
HibernateUtil.beginTransaction();
// checking if the username/password is valid.
boolean loginFailed = false;
pSmt = connection.prepareStatement(queryCheckExistance);
pSmt.setString(1, userDto.getUserName());
pSmt.setString(2, userDto.getPwd());
rs = pSmt.executeQuery();
while (rs.next()) {
int cnt = rs.getInt(1);
if (cnt == 0) {
loginFailed = true;
}
}
System.out.println("loginFailed = " + loginFailed);
if (loginFailed) {
/*
* pSmt = connection.prepareStatement(queryInsertLoginStatus);
*
* pSmt.setInt(1, userDto.getUserId()); pSmt.setString(2, "N");
* pSmt.setString(3, userDto.getUserIP()); pSmt.setString(4,
* "N");
*
* pSmt.execute();
*/
HibernateUtil.commitTransaction();
throw new QnsAndAnsException(
"Sorry! username/password does not match. Please try again.");
}
// get the user id.
pSmt = connection.prepareStatement(queryGetUserId);
pSmt.setString(1, userDto.getUserName());
pSmt.setString(2, userDto.getPwd());
rs = pSmt.executeQuery();
while (rs.next()) {
userId = rs.getInt(1);
}
// checking if the user is already logged in.
pSmt = connection.prepareStatement(queryCheckLogInStatus);
pSmt.setInt(1, userId);
rs = pSmt.executeQuery();
if (rs.next()) {
String logInFlag = rs.getString(1);
if (logInFlag != null && logInFlag.equals("Y")) {
HibernateUtil.commitTransaction();
throw new QnsAndAnsException(
"User already logged in. If you suspect malicious usage of your account, " +
"please change the password from Edit Profile link.");
}
}
pSmt = connection.prepareStatement(queryGetUserDetails);
pSmt.setInt(1, userId);
rs = pSmt.executeQuery();
while (rs.next()) {
userDto.setUserId(rs.getInt("user_id"));
userDto.setUserName(rs.getString("user_name"));
userDto.setUserEmail(rs.getString("user_email"));
}
/*
* pSmt = connection.prepareStatement(queryUpdateLoginStatus);
*
* pSmt.setInt(1, userDto.getUserId());
*
* pSmt.executeUpdate();
*/
stmt = connection.createStatement(
java.sql.ResultSet.TYPE_FORWARD_ONLY,
java.sql.ResultSet.CONCUR_UPDATABLE);
stmt
.executeUpdate(
"insert into user_login (user_id, login_attempt_success_fg, login_ip, user_loggedin_fg)"
+ "values ("
+ userId
+ ", 'Y', '"
+ userDto.getUserIP()
+ "', 'Y')",
Statement.RETURN_GENERATED_KEYS);
// pSmt.execute();
int autoIncKeyFromApi = -1;
rs = stmt.getGeneratedKeys();
if (rs.next()) {
autoIncKeyFromApi = rs.getInt(1);
} else {
autoIncKeyFromApi = -1;
}
System.out.println("autoIncKeyFromApi = " + autoIncKeyFromApi);
userDto.setLoginId(autoIncKeyFromApi);
System.out.println("goging to commit the transaction 3");
HibernateUtil.commitTransaction();
It's giving error every time I am trying to commitTransaction.
One more thing, when the user comes to the Home page I am making a call to the database and that's working fine. This login module is the 2nd call I am trying to make. So basically the 1st operation is working fine. From 2nd operation it's failing.
You might want to try Trasaction:
Transation tx = null;
conn = getConnection();
try {
tx = conn.beginTransaction();
// your code
// if all good
tx.commit();
}
catch (HibernateException e) {
// a problem
if (tx != null)
tx.rollback();
}
finally {
conn.close(); // very important or you will leak connections
}
Hope that helps.
A few things to note here real quick: first it looks like you DAO object may be doing a bit too much. The DAO should be only for data access, the logic to handle logins and such should either be in a domain object or a service layer object.
I was having a similar problem and I had to set the flush mode for the session manually.
org.hibernate.Session session = HibernateUtil.getSession();
Transaction transaction = null;
session.setFlushMode(FlushMode.MANUAL);
transaction = session.beginTransaction();
...
transaction.commit();
This was happening whenever I'd have another select query or whatnot that that would happen within the context of a transaction.
精彩评论