我有这样的实体:
@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 }
评估部件是从评估实体延迟加载的。我也有弹簧控制器方法,它是数据库的事务和负载评估部分:
@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集合),而只会初始化集合(而不是其中的元素)。
通过OpenEntityManagerInViewFilter在您的Web配置中配置,可以强制entitymanager保持打开状态。
OpenEntityManagerInViewFilter
或更改您的控制器代码以包含一个调用Hibernate.initialize以正确初始化您的集合。
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 }
要么创建一个自定义查询,以强制获取集合。