在使用hibernate的spring mvc应用程序中,我收到以下错误消息:
root cause
org.hibernate.LazyInitializationException:
failed to lazily initialize a collection of role:
org.springframework.samples.knowledgemanager.model.Encounter.providers,
could not initialize proxy - no Session
当我尝试访问另一个arraylist中每个对象的属性arraylist时,抛出错误。具体来说,我有一个名为Encounter
的{{1}}个对象的arraylist,每个encountersforday
个对象都有一个属性提供者,它是Encounter
个对象的arraylist。当我尝试使用spring表达式语言从jsp调用Provider
arraylist时抛出错误,如下所示:
providers
上面的代码引用了以下控制器代码:
<spring:eval expression="encountersforday.get(2).getProviders()" var="myps" />
<c:forEach var="id" items="${myps}" varStatus="k">//this is the line throwing error
<spring:eval expression="id==3" var="match_id"></spring:eval>
<c:choose>
<c:when test="${match_id==true}">true</c:when>
<c:otherwise>false</c:otherwise>
</c:choose>
</c:forEach>
//获取日历中列的提供者列表
列表ps =(列表)clinicService.findProvidersByFacilityAddressId(7);
model.addAttribute(“ps”,ps);
for(int g = 0; g
@RequestMapping("/calendar")
public String showCalendar(@RequestParam("day") String day, org.springframework.web.context.request.WebRequest webRequest, Model model) {
String pid = webRequest.getParameter("pid");
System.out.println("............ pid is: "+pid);
model.addAttribute("pid", pid);
LocalDate mydate;
if(day.equals("")){mydate = new LocalDate();}
else{mydate = new LocalDate(day);}
System.out.println("------------------------ in controller, day of month is: "+mydate.getDayOfMonth());
AppointmentCalendar calendar = new AppointmentCalendar(mydate); // Or whatever you do to create it
List<Encounter> encountersforday = (List<Encounter>) clinicService.getEncountersForDay(mydate);
model.addAttribute("calendar", calendar);
model.addAttribute("encountersforday", encountersforday);
System.out.println("number of encountersforday is: "+encountersforday.size());
List<LocalTime> myblocks = calendar.getBlocks();
int[][] filledblocks = new int[myblocks.size()][3];
for(Integer i=0;i<encountersforday.size();i++){
System.out.println("i, encounterid, patientid, first, last, dateTime are: "+i+", "+encountersforday.get(i).getId()+", "
+encountersforday.get(i).getPatient().getId()+", "+encountersforday.get(i).getPatient().getFirstName()+", "+encountersforday.get(i).getPatient().getLastName()+", "+encountersforday.get(i).getDateTime());
for(Integer g=0;g<myblocks.size();g++){
filledblocks[g][0] = g;//blockid
if(myblocks.get(g).getHourOfDay()==encountersforday.get(i).getDateTime().getHourOfDay()){
if(myblocks.get(g).getMinuteOfHour()==encountersforday.get(i).getDateTime().getMinuteOfHour()){
int hours = myblocks.get(g).getHourOfDay();
int mins = myblocks.get(g).getMinuteOfHour();
System.out.println("found match at: "+hours+":"+mins);
filledblocks[g][1] = i+1;//encounterid
filledblocks[g][2] = 1;//segmentindex
}
}
}
}
for(int k=0;k<filledblocks.length;k++){
System.out.println("blockid, encounterid, segmentnum are: "+filledblocks[k][0]+", "+filledblocks[k][1]+", "+filledblocks[k][2]);
}
model.addAttribute("filledblocks", filledblocks);
点击以下链接可以在文件共享网站上找到实际实体的代码:
可以找到 return "appointments/calendar";
}
实体的代码at this link
可以找到Encounter
实体的代码at this link。
这是完整的堆栈跟踪:
Provider
答案 0 :(得分:4)
不知何故(它在您发布的代码中不可见,并且不是非常重要)您的clientService
正在使用Session
对象来获取Encounter
个对象的列表。该Session对象具有close
方法,该方法在Session
完成时调用。调用close
方法后,除非已初始化,否则无法访问延迟初始化的属性。
这让大多数人感到高兴,因为大多数人实际上并没有自己打开和关闭Hibernate会话,而是由底层框架处理。例如,如果您使用的是Spring,则可能会使用@Transactional
和@PersistenceContext
注释,这些注释是开启和关闭会话(在这种情况下,会话在事务结束时关闭,例如你离开@Transactional
方法的范围。
最终,无论你做什么,可用的解决方案都是一样的。最简单的解决方案是简单地将Encounter的提供者关系标记为渴望关系(例如@ManyToMany(... fetch=FetchType.EAGER ...)
),但如果有很多地方加载Encounter对象而不是Provider对象,这可能会影响性能。
另一个“全局”解决方案是扩展您的事务范围,以便JSP的处理实际上在您的事务处理请求中。这通常通过将事务的开始和停止放在过滤器中来完成。虽然有时这对人们也不起作用。
一个非常有针对性的解决方案是在将每个对象传递给JSP层之前使用静态方法Hibernate.initialize()
进行初始化:
List<Encounter> encountersforday = (List<Encounter>) clinicService.getEncountersForDay(mydate);
for(Encounter encounter: encountersforday) {
Hibernate.initialize(encounter.getProviders());
}
也可能有其他解决方案,但这些都是想到的。我希望你能在这方面取得进展。