LEFT JOIN FETCH不工作-Spring数据JPA



我在使用LEFT JOIN FETCH时遇到一个问题。请参阅我下面的实体和存储库。

考虑一个场景,在该场景中,选修课程在任何时间点都不会从表中删除。但是学生信息可以被删除。数据库中的两个表之间并没有主键和外键关系。只是我们有共同的专栏";学生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(((时,它在不存在学生记录(即OptionalCourse到学生协会(的情况下不立即返回null;生成的查询具有正确的语法LEFT OUTER JOIN,在SQLDeveloper中它给出了预期的结果。我们使用的是Oracle数据库。

我犯了什么错误?我不被允许使用EAGER FETCH策略。请通过Lazy Fetch本身帮助解决此问题。提前感谢!!!!

我猜您使用的是在Spring中默认启用的OSIV(视图中的打开会话(反模式?这是这种方法的一个常见问题。问题是,您的一级缓存(持久性上下文(包含具有未初始化的student字段代理的实体。现在,即使您再次选择该实体并加入获取关联,Hibernate也不会替换对象,因为它必须保留对象标识,也不会替换代理。要解决这个问题,您必须在使用EntityManager.clear()进行查询之前清除持久性上下文

最新更新