我有一个带有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)
答案 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);
}
答案 2 :(得分:0)
您如何获取会话SessionFactory.openSession()
或SessionFactory.getCurentSession()
?请记住,休眠会话不是线程安全的,因此每个请求响应周期需要一个会话。