Hibernate Session Closed Exception,当10个或更多用户访问该页面时

时间:2016-10-17 07:37:50

标签: java hibernate spring-mvc


我有一个带有hibernate的spring MVC应用程序。当10个或更多用户访问同一页面以读取数据或快速后续请求后,我继续得到会话关闭错误。 请帮助,我需要一个关键的修复。它正在影响客户。

我使用以下代码

try{
    session = sessionFactory.openSession();
    tx = session.getTransaction();
    session.beginTransaction();
    Map<Organization, List<Users>> comToUserLst 
                           = new HashMap<Organization,List<Users>>();

    String queryString = "FROM Users as usr Inner Join usr.organization 
                          as org     where org.id = :id";

    Query query = session.createQuery(queryString);
    query.setInteger("id", Integer.valueOf(id));

    List<?> comLst = query.list();
    Iterator<?> ite = comLst.iterator();
    while (ite.hasNext()) {
        Object[] objects = (Object[]) ite.next();

        Users user = (Users) objects[0];

        Organization Organization = (Organization) objects[1];
        if (comToUserLst.containsKey(Organization)) {
            List<Users> usrLst = new ArrayList<Users>();
            usrLst.addAll(comToUserLst.get(Organization));
            usrLst.add(user);
            comToUserLst.put(Organization, usrLst);
        } else {
            List<Users> userLst = new ArrayList<Users>();
            userLst.add(user);
            comToUserLst.put(Organization, userLst);
        }
    }

 } catch (HibernateException e) {
    tx.rollback();
    e.printStackTrace();
 } finally {
    tx.commit();
    session.close();
 }
 return comToUserLst;

更新

 @Transactional
    public Account updateAccount(Account account, UserDetail userInfo) {

        session = sessionFactory.getCurrentSession();


        Account acct = null;

        String queryString = "FROM Account where id = :acctId";
        Query query = session.createQuery(queryString);
        query.setLong("acctId", account.getId());

        acct = (Account) query.uniqueResult();

        acct.setName(account.getName());
        acct.setPhone(account.getPhone());
        acct.setRating(account.getRating());
        acct.setFax(account.getFax());
        acct.setAccountNumber(account.getAccountNumber());
        if (!ValidateUtil.isNullOrEmptyCheckStr(account.getParentAccount()
                .getName())) {
            acct.setParentAccount(account.getParentAccount());
        }
        acct.setWebsite(account.getWebsite());
        acct.setType(account.getType());
        acct.setIndustry(account.getIndustry());
        acct.setNumberOfEmployees(account.getNumberOfEmployees());
        acct.setDescription(account.getDescription());
        acct.setAnnualRevenue(account.getAnnualRevenue());
        acct.setEmail(account.getEmail());

        acct.setBillingAddress(account.getBillingAddress());
        acct.setShippingAddress(account.getShippingAddress());

        Users user = new Users();
        user.setId(userInfo.getUserId());
        // modified details
        acct.setModifiedBy(user);
        acct.setModifiedDate(new Date());
        //update use merge
        session.merge(acct);
        session.flush();

        System.out.println("update Account" + acct.getId());

        return acct;
    }

例外

 org.hibernate.SessionException: Session is closed!
        at org.hibernate.internal.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:133)
        at org.hibernate.internal.SessionImpl.getTransactionCoordinator(SessionImpl.java:2069)
        at org.hibernate.loader.Loader.doQuery(Loader.java:923)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354)
        at org.hibernate.loader.Loader.doList(Loader.java:2553)
        at org.hibernate.loader.Loader.doList(Loader.java:2539)
        at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2369)
        at org.hibernate.loader.Loader.list(Loader.java:2364)
        at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:496)
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:387)
        at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:231)
        at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1264)
        at org.hibernate.internal.QueryImpl.list(QueryImpl.java:103)
        at com.oi.service.setup.OrganizationService.getOrgToUserLst(OrganizationService.java:311)
        at com.oi.service.setup.OrganizationService$$FastClassBySpringCGLIB$$84e99831.invoke(<generated>)
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)

3 个答案:

答案 0 :(得分:0)

您应该使用sessionFactory.getCurrentSession()代替openSession()。这将自动维持开始和结束会话。 你也应该使用@Transactional和你的方法使用Spring的交易。 Spring的事务管理比Hibernate的getCurrentTransaction()更有效

答案 1 :(得分:0)

在Spring中,可能需要看起来像这样:

@Autowired
private SessionFactory sessionFactory;

public void setSessionFactory(SessionFactory sessionFactory) {
    this.sessionFactory = sessionFactory;
}

@Transactional
public Map getOrgToUserLst() {
    Map<Organization, List<Users>> comToUserLst = new HashMap<Organization,List<Users>>();
    String queryString = "FROM Users as usr Inner Join usr.organization as org where org.id = :id";

    List<?> comLst = this.sessionFactory.getCurrentSession()
            .createQuery(queryString)
            .setParameter(0, Integer.valueOf(id))
            .list();
    Iterator<?> ite = comLst.iterator();

    while (ite.hasNext()) {
        Object[] objects = (Object[]) ite.next();

        Users user = (Users) objects[0];

        Organization Organization = (Organization) objects[1];
        if (comToUserLst.containsKey(Organization)) {
            List<Users> usrLst = new ArrayList<Users>();
            usrLst.addAll(comToUserLst.get(Organization));
            usrLst.add(user);
            comToUserLst.put(Organization, usrLst);
        } else {
            List<Users> userLst = new ArrayList<Users>();
            userLst.add(user);
            comToUserLst.put(Organization, userLst);
        }
    }

    return comToUserLst;
}

@Transactional
public void saveOrganization(Organization org) {
    this.sessionFactory.getCurrentSession().persist(org);
}

@Transactional
public void updateOrganization(Organization org) {
    this.sessionFactory.getCurrentSession().merge(org);
}

@Transactional
public void deleteOrganization(Organization org) {
    getCurrentSession().delete(org);
}

@Transactional
public void deleteOrganizationById(long id) {
    final Organization org = this.getCurrentSession().get(Organization, id);
    this.getCurrentSession().delete(org);
}

FOR UPDATE

// Get an account object by ID
public Account getAccount(long id) {
    session = sessionFactory.getCurrentSession();
    String queryString = "FROM Account where id = :acctId";
    Query query = session.createQuery(queryString);
    query.setLong("acctId", id);
    return (Account) query.uniqueResult();
}

// Set account object's attributes
public Account updateAccount(Account acct, UserDetail userInfo) {
    acct.setName(account.getName());
    acct.setPhone(account.getPhone());
    acct.setRating(account.getRating());
    acct.setFax(account.getFax());
    acct.setAccountNumber(account.getAccountNumber());
    if (!ValidateUtil.isNullOrEmptyCheckStr(account.getParentAccount()
            .getName())) {
        acct.setParentAccount(account.getParentAccount());
    }
    acct.setWebsite(account.getWebsite());
    acct.setType(account.getType());
    acct.setIndustry(account.getIndustry());
    acct.setNumberOfEmployees(account.getNumberOfEmployees());
    acct.setDescription(account.getDescription());
    acct.setAnnualRevenue(account.getAnnualRevenue());
    acct.setEmail(account.getEmail());

    acct.setBillingAddress(account.getBillingAddress());
    acct.setShippingAddress(account.getShippingAddress());

    Users user = new Users();
    user.setId(userInfo.getUserId());
    // modified details
    account.setModifiedBy(user);
    account.setModifiedDate(new Date());
    updateAccount(acct);
}

// Update the account object in the database. Here transaction is necessary
@Transactional
private Account updateAccount(Account acct) {
    session = sessionFactory.getCurrentSession();
    //update use merge
    System.out.println("update Account" + acct.getId());
    return session.merge(acct);
}

// This is for testing
public void testUpdate(long id, UserDetail userInfo) {
    Account acc = getAccount(id);
    updateAccount(acct, userInfo);
}

Reference

答案 2 :(得分:0)

您如何获取会话SessionFactory.openSession()SessionFactory.getCurentSession()?请记住,休眠会话不是线程安全的,因此每个请求响应周期需要一个会话。