我的一位朋友在开源软件OscarMcmaster
中遇到了一个奇怪的问题。他让我帮忙,我能够解决造成问题的代码。以下是一种方法:
public BillingService getBillingCodeByCode(String code){
List list = billingServiceDao.findBillingCodesByCode( code,"BC");
if(list == null || list.size() ==0 ){
return null;
}
return (BillingService) list.get(0);
}
billingServiceDao
由Spring
容器初始化:
private static BillingServiceDao billingServiceDao =
(BillingServiceDao) SpringUtils.getBean("billingServiceDao");
在BillingServiceDao
类中执行以下代码:
public List<BillingService> findBillingCodesByCode(String code, String region) {
Query query = entityManager.createQuery("select bs from....");
query.setParameter("code", code + "%");
query.setParameter("region", region);
@SuppressWarnings("unchecked")
List<BillingService> list = query.getResultList();
return list;
}
罪魁祸首是query.getResultList();
,但我来自其他宇宙(.Net)并且不知道该问题的补救措施。
请帮我帮朋友解决这个问题。
编辑: - 堆栈跟踪
SEVERE: Servlet.service() for servlet action threw exception
org.hibernate.HibernateException: collection is not associated with any session
at org.hibernate.collection.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:449)
at org.hibernate.engine.StatefulPersistenceContext.initializeNonLazyCollections(StatefulPersistenceContext.java:797)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:241)
at org.hibernate.loader.Loader.doList(Loader.java:2220)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2104)
at org.hibernate.loader.Loader.list(Loader.java:2099)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:378)
at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:338)
at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:172)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1121)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:79)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:66)
at org.oscarehr.common.dao.BillingServiceDao.findBillingCodesByCode(BillingServiceDao.java:47)
at org.oscarehr.common.dao.BillingServiceDao$$FastClassByCGLIB$$f613fb7e.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
答案 0 :(得分:4)
默认情况下,Hibernate会填充列表对象&#34;懒惰&#34;,为此,您需要打开会话。 Spring正在围绕对DAO的调用打开和关闭Hibernate会话。因此,当您去检查列表时,Hibernate会尝试为您填充它,但它会发现会话已关闭并引发错误。
您需要向web.xml添加OpenSessionInViewFilter(假设您正在编写Web应用程序),将SpringSessionInViewInterceptor添加到spring上下文中,或者在返回之前简单地提取列表内容:
return new ArrayList<BillingService>(list);
另外,请注意:
private static BillingServiceDao billingServiceDao =
(BillingServiceDao) SpringUtils.getBean("billingServiceDao");
首先完全违背了使用Spring的目的。
答案 1 :(得分:0)
我看到了这个问题,因为我未能使用@Transactional
在服务中注释方法。似乎Hibernate在调用另一个方法时(即使在同一个类中)关闭会话,除非调用者被正确注释。