![](/img/trans.png)
[英]Hibernate LazyInitializationException using Spring CrudRepository
[英]Hibernate LazyInitializationException while using collection in Spring JSP page
我有這樣的實體:
@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 控制器方法,它是事務性的,並從數據庫中加載評估部分:
@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 不應該加載任何東西,因為它已經加載了。 為什么會發生這種奇怪的事情?
在視圖中,entitymanager 已經關閉,因此集合中的元素無法檢索那里的屬性。 您在控制器中編寫的代碼不會初始化集合中的元素(它是一個 LAZY 集合),而只會初始化集合(而不是其中的元素)。
通過在 Web 配置中配置OpenEntityManagerInViewFilter
強制實體管理器保持打開狀態。
或者更改您的控制器代碼以包含對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
}
或者創建一個自定義查詢,強制急切地獲取集合。
改變
model.put("assessmentParts", assessment.getAssessmentParts());
到
Hibernate.initialize(assessment.getAssessmentParts());
初始化您的收藏。
方法調用assessment.getAssessmentParts()
未初始化您的集合。 此方法調用將只返回一個集合包裝器,您需要將此包裝器傳遞給Hibernate.initialize
方法以進行手動初始化。
編輯:
使用 JPA,您可以使用 JPQL Fetch Joins 獲取AssessmentParts
以及Assessment
(任何需要的地方),覆蓋默認行為:
SELECT a FROM Assessment asmt LEFT JOIN FETCH asmt.assessmentParts WHERE asmt.id = :id
從 EntityManager 加載 AssessmentPart 將加載 Assessment @ManyToOne(fetch = FetchType.EAGER)
AssessmentPart assessmentPart = //laods a part with entity manager
Assessment assessment = assessmentPart.getAssessment();
嘗試從評估中提取 AssessmentParts 將不起作用,因為它不是@OneToMany(fetch = FetchType.LAZY)
並且會話已經關閉
model.put("assessmentParts", assessment.getAssessmentParts());
使用新方法從 EntityManager 中通過 Assessment 獲取 AssessmentParts 列表應該可以解決問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.