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

标签 java spring hibernate jsp 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
}

另一个:

@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
}

评估部分是从评估实体延迟加载的。我还有 spring Controller 方法,它是事务性的,并从数据库加载评估部分:

@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
}

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

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

此 JSP 页面抛出异常:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: my.package.something.Assessment.assessmentParts, could not initialize proxy - no Session

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

最佳答案

在 View 中,entitymanager 已经关闭,因此您集合中的元素无法检索那里的属性。您在 Controller 中编写的代码不会初始化集合中的元素(它是一个 LAZY 集合),而只会初始化集合(而不是其中的元素)。

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

或者更改您的 Controller 代码以包含对 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
}

或者创建一个自定义查询,强制预先获取集合。

关于java - 在 Spring JSP 页面中使用集合时出现 Hibernate LazyInitializationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19047835/

相关文章:

java - 包含字节数组列表的方法

java - 不能在 JFrame 中绘制超过一个正方形

java - Spring Boot中update方法的实现

没有嵌入tomcat的spring boot war

java - 'hibernate.dialect' 必须在没有连接可用错误时设置

java - 从 ArrayList 中删除子列表

java - 如果返回类型为 java.sql.Timestamp,则基于接口(interface)的投影 getter 方法给出异常

java - 指定全局EhCache容量

hibernate - CGLIB 增强失败 :argument type mismatch

java - HashMap 的 ContainsKey 不适用于自定义类作为键