在Spring JSP页面中使用集合时出现Hibernate LazyInitializationException

use*_*247 4 java spring jsp hibernate spring-mvc

我有这样的实体:

@Entity
@Table(name = "ASSESSMENT")
public class Assessment {

    //All other fields..

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "assessment")
    @OrderBy(value = "order ASC")
    private List<AssessmentPart> assessmentParts = new LinkedList<>();

    public List<AssessmentPart> getAssessmentParts() {
        return assessmentParts;
    }

    //All other getters/setters
}
Run Code Online (Sandbox Code Playgroud)

另一个:

@Entity
@Table(name = "ASSESSMENT_PART")
public class AssessmentPart {

    //All other fields

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "ASSESSMENT_ID", nullable = false)
    private Assessment assessment;

    public Assessment getAssessment() {
        return assessment;
    }

    public void setAssessment(Assessment assessment) {
        this.assessment = assessment;
    }

    //All other getters/setters
}
Run Code Online (Sandbox Code Playgroud)

评估部分从评估实体延迟加载.我也有弹簧控制器方法,它是Transactional并从数据库加载评估部分:

@Transactional
public void doSomething(String partId, Map<String, Object> model) {

    AssessmentPart assessmentPart = //laods a part with entity manager
    Assessment assessment = assessmentPart.getAssessment(); //Getting the assessments

    model.put("assessmentParts", assessment.getAssessmentParts()); //adding all assessments parts into spring model map
}
Run Code Online (Sandbox Code Playgroud)

一旦我将评估部分添加到spring模型映射中,它们就可以在我的JSP页面中使用了,我使用JSTL循环遍历它们:

<c:forEach var="assessmentPart" items="${assessmentParts}">
     //Not loading any lazy stuff, just getting an ID of assessment part
</c:forEach>
Run Code Online (Sandbox Code Playgroud)

从这个JSP页面抛出异常:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: my.package.something.Assessment.assessmentParts, could not initialize proxy - no Session
Run Code Online (Sandbox Code Playgroud)

如果此集合已在事务中加载,这怎么可能?我只是试图循环,hibernate此时不应该加载任何东西,因为它已经加载了.为什么会发生这种奇怪的事情?

M. *_*num 6

在视图中,entitymanager已经关闭,因此集合中的元素无法检索那些属性.您在控制器中编写的代码不会初始化集合中的元素(它是一个LAZY集合),但只初始化集合(而不是其中的元素).

通过OpenEntityManagerInViewFilter在Web配置中配置,强制实体管理器保持打开状态.

或者更改您的控制器代码以包含调用Hibernate.initialize以正确初始化您的集合.

@Transactional
public void doSomething(String partId, Map<String, Object> model) {

    AssessmentPart assessmentPart = //laods a part with entity manager
    Assessment assessment = assessmentPart.getAssessment(); //Getting the assessments
    Hibernate.initialize(assesment.getAssesmentParts()); // Init collection
    model.put("assessmentParts", assessment.getAssessmentParts()); //adding all assessments parts into spring model map
}
Run Code Online (Sandbox Code Playgroud)

要么是这样,要么创建一个强制急切提取集合的自定义查询.