当前位置: 首页 > 知识库问答 >
问题:

左连接提取不工作-Spring数据JPA

马哲
2023-03-14

我在使用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)时,为什么在学生记录不存在的情况下(即学生协会的可选课程),它不会立即返回null。getStudent();生成的查询语法正确,如LEFT OUTER JOIN,在SQLDeveloper中,它给出了预期的结果。我们正在使用Oracle数据库。

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

共有1个答案

薛阳荣
2023-03-14

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

 类似资料:
  • 早上好, 我正在进行SQL学习之旅,并试图创建一个带有一些查询的小型数据库以获得经验。使用的两个数据库,Person{id, name, age}和Knows{id,guest1_id→人员,guest2_id→人员} 查询应该会产生一个不认识数据库中任何人但可以被其他人知道的人的姓名列表。下面是我到目前为止得到的代码,但它似乎没有获得任何东西。 这里有什么问题? 非常感谢。

  • 这是我的命名查询: @NamedQuery(name=“User.findOneWithLists”,query=“从用户u中选择u”“左连接获取u.aTemplates”“左连接获取u.bTemplates”“左连接获取u.bp”“左连接获取u.aCredentials”“左连接获取u.st WHERE(st.deleted=false)”“左连接获取u.bCredentials”“左连接获取u

  • 我正在尝试使用Spring数据JPA Specification来查询数据,但这里有一些问题。Java代码如下: 当我注释代码“收件人NoticeJoin.fetch(UserNoticeEntity_. user, JoinType. INNER);”时,它工作正常,但当我取消注释时,我会得到错误: 所以,我想知道使用规范方式是否支持连接获取,或者我的代码有问题。我知道使用@Query(“一些h

  • 当我添加一个左连接来获取外部表的计数时,它将我其他左连接表的总和值与计数相乘,我也不能在这里使用不同的总和,因为两个值可以是相同的:

  • 我有多张谷歌表。所有数据列都具有相同的名称(id、日期、金额),但列数不同:在第1页中,“id”列是A列,在第2页中“id”列可以是C列或任何其他列。 我正在尝试创建一个主工作表,从所有工作表中提取所有数据并按列名排列。尝试使用Query,但它似乎可以与列id(A,B)一起工作,而在我的例子中,id(A,B)正在发生变化。 这是一张样品单

  • 我使用的是spring-data-jpa。我写了一个本机查询,但它不起作用。这是我的实体类: 以下是查询: 起初,当我没有编写nativeQuery=true时,应用程序没有构建,我得到了一个异常“加入jpa的预期路径”。当我设置nativeQuery=true时,应用程序已启动,但当我调用该函数时,我收到以下错误: 是否有任何其他设置或注释可以解决此问题?我在谷歌上搜索过,但在所有情况下都有两个