session管理方面的问题,session是线程不安全的,不同于sessionfactory,你程序里面的俩个方法申请的session实际上对应同一个实例,所以两个方法都想关掉session时会出错,只对其中一个操作就没事,解决方法可参照夏昕的hibernate开发指南,ThreadLocal解决session线程安全问题

解决方案 »

  1.   

    main中的2个操作是放在一个session里面来做的。
      

  2.   

    加一个过滤器在一次请求完成以后去统一关闭session,而在你的数据库操作方法里都不关闭session.
      

  3.   

    package cn;import java.io.IOException;import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.*;import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;public class CloseSessionFilter implements Filter {
    Log logger = LogFactory.getLog(this.getClass());
    /* (non-Javadoc)
     * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
     */
    protected FilterConfig config;
    public void init(FilterConfig arg0) throws ServletException {
    // TODO Auto-generated method stub
    this.config = arg0;
    } /* (non-Javadoc)
     * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
     */
    public void doFilter(
    ServletRequest request,
    ServletResponse response,
    FilterChain chain)
    throws IOException, ServletException {
    // TODO Auto-generated method stub
    try{
    chain.doFilter((HttpServletRequest)request, (HttpServletResponse)response);
    }
    finally{
    try{
    HibernateUtil.commitTransaction();
    //System.out.println("commit ok");
    }catch (Exception e){
    HibernateUtil.rollbackTransaction();
    }finally{
    HibernateUtil.closeSession();
    System.out.println("session close");

    }   
    }
    } /* (non-Javadoc)
     * @see javax.servlet.Filter#destroy()
     */
    public void destroy() {
    // TODO Auto-generated method stub
    this.config = null;
    }}
      

  4.   

    另外HibernateUtil 类
    package cn;
    //import net.sf.hibernate.cfg.*;
    //import net.sf.hibernate.*;
    //import javax.transaction.Transaction;import org.hibernate.*;
    import org.hibernate.cfg.Configuration;
    public class HibernateUtil {
        private static final SessionFactory sessionFactory;    static {
            try {
                // Create the SessionFactory
                sessionFactory = new Configuration().configure()
                        .buildSessionFactory();
            } catch (Throwable ex) {
                ex.printStackTrace();
                System.out.println("Initial SessionFactory creation failed.");
                throw new ExceptionInInitializerError(ex);
            }
        }    public static final ThreadLocal tLocalsess = new ThreadLocal();    public static final ThreadLocal tLocaltx = new ThreadLocal();    /*
         * getting the thread-safe session for using
         */
        public static Session currentSession() {
            Session session = (Session) tLocalsess.get();        //open a new one, if none can be found.
            try {
                if (session == null || !session.isOpen()) {
                    session = openSession();
                    tLocalsess.set(session);
                }
            } catch (HibernateException e) {
                //throw new HibernateException(e);
                e.printStackTrace();
            }
            return session;
        }    /*
         * closing the thread-safe session
         */
        public static void closeSession() {        Session session = (Session) tLocalsess.get();
            tLocalsess.set(null);
            try {
                if (session != null && session.isOpen()) {
                    session.close();
                    System.out.println("session close");
                }        } catch (HibernateException e) {
                //throw new InfrastructureException(e);
            }
        }    /*
         * begin the transaction
         */
        public static void beginTransaction() {
            System.out.println("begin tx");
            Transaction tx = (Transaction) tLocaltx.get();
            try {
                if (tx == null) {
                    tx = currentSession().beginTransaction();
                    tLocaltx.set(tx);
                }
            } catch (HibernateException e) {
                //throw new InfrastructureException(e);
            }
        }    /*
         * close the transaction
         */
        public static void commitTransaction() {
            Transaction tx = (Transaction) tLocaltx.get();
            try {
                if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack())
                    tx.commit();
                
                tLocaltx.set(null);
                System.out.println("commit tx");
            } catch (HibernateException e) {
                //throw new InfrastructureException(e);
            }
        }    /*
         * for rollbacking
         */
        public static void rollbackTransaction() {
            Transaction tx = (Transaction) tLocaltx.get();
            try {
                tLocaltx.set(null);
                if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()) {
                    tx.rollback();
                }
            } catch (HibernateException e) {
                //throw new InfrastructureException(e);
            }
        }    private static Session openSession() throws HibernateException {
            return getSessionFactory().openSession();
        }    private static SessionFactory getSessionFactory() throws HibernateException {
            return sessionFactory;//SingletonSessionFactory.getInstance();
        }
    }
      

  5.   

    你的 sessionFactory 是 hibernate 帮你生成的 sessionFactory类吧,而不是 hibernate 带的 SessionFactory,因为它用了ThreadLocal把session保存成线程局部变量,当你调用完第一个查询 session.close()第二次查询的时候 sessionFactory.getSession()发现本地线程中的session不是null(只是closed),所以也会拿出来执行查询,所以造成session.closed异常解决办法有二:
    1,你应该通 sessionFactory的closeSession()方法(自己看看代码是叫什么方法)或关闭session,它不仅会把session close,还会把session从TLS(在win32下就叫做Thread Local Store, 线程局部存储),让下次 getSession()时取到的是一个open的session
    2,上面有人介绍的那样采用OpenSessionInView的模式,在一个请求中共用一个session,这样只是session的生命期会长些好好理解MyEclipse帮你生成的那个 sessionFactory类的实现,以及了解TLS知识。
      

  6.   

    1,你应该通 sessionFactory的closeSession()方法(自己看看代码是叫什么方法)或关闭session,它不仅会把session close,还会把session从TLS(在win32下就叫做Thread Local Store, 线程局部存储),让下次 getSession()时取到的是一个open的session
    这个讲的有点模糊,楼上的大哥能不能再把这个方法讲清楚点呢?
      

  7.   

    需要把sessionFactory.getSession();发出给看看才好
      

  8.   

    留个记号,回头再来see see
      

  9.   

    单表肯定是不会出现session关闭的情况的
    这个情况要么 就在xml里面 把Lazy改成false
    要么就在查询的时候 fetch一下
      

  10.   

    大家看这个帖"spring+hibernate一个困扰几天的问题? " 老是报session closed的问题
      

  11.   

    汗 SessionFactory 每次 getSession不是创造一个新的session啊.....session.close()也不是析构掉这个session啊......瀑布汗.......看来我的实现也要改咯...........倒真没做并发测试......
      

  12.   

    session管理方面的问题,session是线程不安全的,不同于sessionfactory,你程序里面的俩个方法申请的session实际上对应同一个实例,所以两个方法都想关掉session时会出错,只对其中一个操作就没事,解决方法可参照夏昕的hibernate开发指南,ThreadLocal解决session线程安全问题
      

  13.   

    myeclispe自动生成的HibernateSessionFactory工具类的getSession()方法得到的session是线程共享的,如果在程序中两次调用close()方法就会出错。
    建议使用HibernateSessionFactory.closeSession()方法关闭session