0

我正在使用 Hibenate 和 Struts 1.3 我收到错误“org.hibernate.SessionException:会话已关闭”。

这是 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;
}

这是 XML 文件:

<!-- 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 -->

    <!-- JDBC 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.ThreadLocal‌​SessionContext</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>

这是我正在使用的 DAO 类:

        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();

每次我尝试提交事务时都会出错。

还有一件事,当用户来到主页时,我正在调用数据库,并且工作正常。此登录模块是我尝试拨打的第二个电话。所以基本上第一次操作工作正常。从第二次操作开始,它失败了。

4

2 回答 2

0

您可能想尝试 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
}

希望有帮助。

于 2011-07-18T15:15:46.397 回答
0

这里有几件事情需要注意:首先看起来你的 DAO 对象可能做的太多了。DAO 应该只用于数据访问,处理登录的逻辑等应该在域对象或服务层对象中。

我遇到了类似的问题,我不得不手动设置会话的刷新模式。

org.hibernate.Session session = HibernateUtil.getSession();
Transaction transaction = null;

session.setFlushMode(FlushMode.MANUAL);

transaction = session.beginTransaction();
...
transaction.commit();

每当我有另一个选择查询或在事务上下文中发生的类似情况时,就会发生这种情况。

于 2011-07-19T01:59:19.197 回答