【发布时间】:2021-09-11 21:46:40
【问题描述】:
我在使用 LEFT JOIN FETCH 时遇到问题。请参考我下面的实体和存储库。
考虑一个场景,选修课程在任何时候都不会从表格中删除。但是可以删除学生信息。 数据库中的两个表之间没有主键和外键关系。只是我们有共同的列“STUDENT_ID”。
@NamedEntityGraphs({
@NamedEntityGraph(
name = "Student.optionalCourse",
attributeNodes = @NamedAttributeNode("optionalCourse")
)
})
@Table("STUDENT")
class Student {
@Id
@column_name(STUDENT_ID)
private integer studentId;
@column_name(STUDENT_AGE)
private int studentAge;
@OneToMany(fetch = FetchType.LAZY, mappedBy="student")
private List<OptionalCourse> optionalCourse;
}
@NamedEntityGraphs({
@NamedEntityGraph(
name = "OptionalCourse.student",
attributeNodes = @NamedAttributeNode("student")
)
})
@Table("OPTIONAL_COURSES")
class OptionalCourse {
@Id
@column_name(ID)
private Integer id;
@column_name(STUDENT_ID)
private Integer studentId;
@column_name(SUBJECT_NAME)
private String subjectName;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "STUDENT_ID" , referencedColumnName="STUDENT_ID", insertable = false, updatable = false )
private Student student;
}
@Repository
@Transactional(rollbackFor = Exception.class)
public interface OptionalCourseRepository extends JpaRepository<OptionalCourse,Integer> {
@Query(value = "SELECT oc FROM OptionalCourse oc LEFT JOIN FETCH oc.student where oc.studentId > :studentId",
countQuery = "SELECT count(oc.id) FROM OptionalCourse oc where oc.studentId > :studentId")
public Page<OptionalCourse> findOptionalSubjectPagesByStudentId(@Param("studentId") Integer studentId, Pageable pageable);
}
没有事务的服务方法:
public List<CustomBeanClass> retrieveRpdLogRequestsList(Integer studentId, Integer pageIndex, Integer pageResultsSize) {
Pageable pageWithIndexAndSize = Pageable.unpaged();
if(Objects.nonNull(pageIndex) && Objects.nonNull(pageResultsSize) && pageIndex >= 0 && pageResultsSize > 0) {
pageWithIndexAndSize = PageRequest.of(pageIndex, pageResultsSize);
}
Page<OptionalCourse> pageData = optionalCourseRepository.findOptionalSubjectPagesByStudentId(studentId, pageWithIndexAndSize);
List<OptionalCourse> pageDataList = pageData.toList();
pageDataList.forEach(course -> {
OptionalCourse oc = course;
//When trying to fetch student info from optional course, when student info is not there then we are getting below error
oc.getStudent(); **//com.sun.jdi.InvocationException: Exception occurred in target VM occurred invoking method hibernate & org.hibernate.LazyInitializationException: could not initialize proxy [com.xxx.xxx.Student#550] - no Session**
});
}
事务性的服务方法:
@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
public List<CustomBeanClass> retrieveRpdLogRequestsList(Integer studentId, Integer pageIndex, Integer pageResultsSize) {
Pageable pageWithIndexAndSize = Pageable.unpaged();
if(Objects.nonNull(pageIndex) && Objects.nonNull(pageResultsSize) && pageIndex >= 0 && pageResultsSize > 0) {
pageWithIndexAndSize = PageRequest.of(pageIndex, pageResultsSize);
}
Page<OptionalCourse> pageData = optionalCourseRepository.findOptionalSubjectPagesByStudentId(studentId, pageWithIndexAndSize);
List<OptionalCourse> pageDataList = pageData.toList();
pageDataList.forEach(course -> {
OptionalCourse oc = course;
//When trying to fetch student info from optional course, when student info is not there then we are getting below error
oc.getStudent(); **// EntityNotFoundException - Its trying to fetch the dependent entity student here**
});
}
即使我使用了 LEFT JOIN FETCH,为什么当我调用依赖实体(即)oc.getStudent();生成的查询具有正确的语法为 LEFT OUTER JOIN,在 SQLDeveloper 中它给出了预期的结果。我们正在使用 Oracle 数据库。
我犯了什么错误?我不被允许使用 EAGER FETCH 策略。请通过 Lazy Fetch 本身帮助解决此问题。提前谢谢!!!!
【问题讨论】:
-
有人可以帮忙解决上述问题吗!!!
标签: spring-boot hibernate jpa orm spring-data-jpa