Hibernate 休眠会话关闭问题!

Hibernate 休眠会话关闭问题!,hibernate,session,jsf,hql,Hibernate,Session,Jsf,Hql,下面的函数是我在web应用程序中的一个按钮的actionListener,我正在从数据库中的表中删除旧的选定行,并将新行插入数据库 public void getSelectedExemptionItems(ActionEvent ae) { Session hibernateSession; Session hibernate2Session; selectedExemptions = new ArrayList<ExemptionBean

下面的函数是我在web应用程序中的一个按钮的actionListener,我正在从数据库中的表中删除旧的选定行,并将新行插入数据库

public void getSelectedExemptionItems(ActionEvent ae) {
        Session hibernateSession;
        Session hibernate2Session;
        selectedExemptions = new ArrayList<ExemptionBean>();
        for (ExemptionBean eBean : exemBean) { // iterating over the list of ExemptionBean class
            if (selectedExemptionIDs.get(eBean.getExemptionID()).booleanValue()) {
                selectedExemptions.add(eBean); // adding every ExemptionBean that is selected.
            }
        }
        // getting importane session variables
        SessionBean1 theSessionBean = (SessionBean1) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("SessionBean1");
        JAdmApplication admApplication = theSessionBean.getAdmApplication();
        long admAppID = admApplication.getJAdmApplicationId();
//        ArrayList<JAdmAppExemption> admAppExemption = (ArrayList<JAdmAppExemption>)theSessionBean.getAdmAppExemption();

        JAdmAppExemption admAppExem = new JAdmAppExemption();

        // try catch : delete all previously chosen exemptions from database by logged-in user.
        try {
            hibernateSession = HibernateUtil.getAdmSessionFactory().getCurrentSession();
            Transaction t = hibernateSession.beginTransaction();
            t.begin();
            String sequel = "DELETE FROM JAdmAppExemption WHERE createdby = ?";
            Query q = hibernateSession.createQuery(sequel);
            q.setParameter(0, theSessionBean.getPortalUserId());

        } catch (Exception e){
            System.out.println("Row could not be deledted from database!!");
        }

//         adding all selected exemptions to the database

        for (ExemptionBean e : selectedExemptions) {
            admAppExem.setAdClientId(1000001);
            admAppExem.setAdOrgId(1000001);
            admAppExem.setCreated(getTimestamp());
            admAppExem.setCreatedby(theSessionBean.getPortalUserId());
            admAppExem.setIsactive('Y');
            admAppExem.setJAdmAppExemptionId(getJAdmAppExemptionIdSequence());
            admAppExem.setJAdmApplicationId(admAppID);
            admAppExem.setJAdmExemptionId(e.getExemptionID());
            admAppExem.setUpdated(getTimestamp());
            admAppExem.setUpdatedby(theSessionBean.getPortalUserId());

            hibernate2Session = HibernateUtil.getAdmSessionFactory().getCurrentSession(); // session is opened here!
            Transaction tx = hibernate2Session.beginTransaction();
            tx.begin();
            try {
                hibernate2Session.beginTransaction();
                hibernate2Session.save(admAppExem); // is it save or saveOrUpdate??
                hibernate2Session.getTransaction().commit();
                updateJAdmAppExemptionIdSequence();

            } catch (Throwable ex){
                if (hibernate2Session.getTransaction().isActive()) {
                    hibernate2Session.getTransaction().rollback();
                }
                ex.printStackTrace();
            }
        }
    }

谢谢,

您在会话范围的托管bean中使用了惰性抓取,而Hibernate会话显然配置为基于请求


长话短说:。

如果有人在Hibernate中遇到这个问题,我会找到一个简洁的答案。显然很简单

在hibernate中使用托管会话简化单元测试2006年11月6日 如果您曾经尝试在Hibernate中重用会话,您可能会遇到此异常

org.hibernate.SessionException: Session is closed!
   at org.hibernate.impl.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:49)
   at org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1319)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
   at java.lang.reflect.Method.invoke(Unknown Source)
   at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:301)
   at $Proxy0.beginTransaction(Unknown Source)
   ....
原因是Hibernate正在使用
thread
managed会话。使用这种类型的会话管理,Hibernate为您管理会话。当您第一次尝试使用会话时,Hibernate将创建一个会话并将其连接到本地线程。当您在会话中提交事务时,Hibernate将自动关闭会话,这意味着它不能被重用

要解决这个问题,最好的选择是使用
managed
会话。使用托管会话,您可以完全控制会话的创建、刷新、提交和关闭。这是怎么做的

hibernate.cfg.xml
中,将属性
current\u session\u context\u class
更改为
managed

要在该
会话中创建
会话
并启动
事务
,请执行以下操作

org.hibernate.classic.Session session = HibernateUtil.getSessionFactory().openSession();
   session.setFlushMode(FlushMode.MANUAL);
   ManagedSessionContext.bind(session);
   session.beginTransaction();
ManagedSessionContext.unbind(HibernateUtil.getSessionFactory());
   session.flush();
   session.getTransaction().commit();
   session.close();
要在
会话
中提交
事务
,请执行以下操作

org.hibernate.classic.Session session = HibernateUtil.getSessionFactory().openSession();
   session.setFlushMode(FlushMode.MANUAL);
   ManagedSessionContext.bind(session);
   session.beginTransaction();
ManagedSessionContext.unbind(HibernateUtil.getSessionFactory());
   session.flush();
   session.getTransaction().commit();
   session.close();
为了在单元测试中使用这段代码,我创建了这个基本单元测试类,所有单元测试都扩展了它。每当我想创建一个新的
会话
事务
时,我调用方法
createNewSessionAndTransaction()
。要提交会话的事务,我调用方法
commitTransaction()


尝试将此添加到控制器方法:

@Transactional(readOnly = true)

这真的很有帮助,应该是公认的答案。