Java Spring异常中的延迟加载

时间:2014-05-19 16:10:53

标签: java spring jpa lazy-loading eager-loading

在我的控制器中,我有以下代码在我的数据库中获取特定的演示文稿,将其添加为模型属性并返回详细信息视图:

@RequestMapping(value = "/detail", method = RequestMethod.GET)
public String detail(Model model, Principal principal, @RequestParam("id") int id) {
        Presentation p = presentationDao.get(id);
        model.addAttribute("presentation", p);
        return "detail";
}

在我看来,我试图使用JSTL显示延迟加载的Presentation的属性:

$ {pressentation.student.dossiers.proposal.titel}

但是在学生中有一个' Dossiers'的列表,但它正在使用延迟加载:

@OneToMany(mappedBy = "student", fetch = FetchType.LAZY)
private List<Dossier> dossiers;

但我得到以下例外:

org.apache.jasper.JasperException: javax.el.ELException: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: domein.Student.dossiers, no session or session was closed

当我将档案的FetchType设置为Eager时,我甚至无法运行我的项目:

Severe:   Exception while loading the app : java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in ServletContext resource [/WEB-INF/dispatcher-servlet.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build EntityManagerFactory

当我用Google搜索时,我找到了以下解决方案:

@RequestMapping(value = "/detail", method = RequestMethod.GET)
    public String detail(Model model, Principal principal, @RequestParam("id") int id) { 
        Presentatie p = presentatieDao.get(id);
        Hibernate.initialize(p.getStudent().getDefinitiefDossier().getVoorstel().getTitel());
        model.addAttribute("presentatie", p);
        return "detail";
}

但它又给了我以下例外:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: domein.Student.dossiers, no session or session was closed

2 个答案:

答案 0 :(得分:1)

您的控制器没有数据库的上下文,因此他无法获取所有延迟加载数据。您需要做的是直接在您的Model对象(可能是presentatieDao DAO)中编写一个方法,并在将所有元素添加到控制器中之前,将此方法中的所有元素添加到列表中。

答案 1 :(得分:0)

您有很多选择:

  1. 你制作收藏品EAGER
  2. 您创建了另一个DAO方法,并将其称为presentatieDao.getWithDossiers(id),您可以在其中执行某些操作以加载档案(如档案集合上的.size())。
  3. 您将控制器方法标记为@Transactional,这将导致会话保持打开并正确获取(但从长远来看可能会减慢您的应用)。
  4. 另一个:

    1. 在视图拦截器http://springtips.blogspot.co.uk/2007/07/open-session-in-view.html
    2. 中尝试打开会话