카테고리 없음

MultipleBagFetchException : 여러 백을 동시에 가져올 수 없습니다.

기록만이살길 2021. 2. 26. 03:21
반응형

MultipleBagFetchException : 여러 백을 동시에 가져올 수 없습니다.

1. 질문(문제점):

다음 항목이 있습니다.

등록 된 프로그램

@Data
@NoArgsConstructor
@Entity
@EntityListeners(RegisteredProgramAuditListener.class)
public class RegisteredProgram extends Auditable<String> {

    @OneToMany(mappedBy = "registeredProgram", cascade = CascadeType.ALL)
    @JsonBackReference
    private List<Trainer> trainerList;

    @OneToMany(mappedBy = "registeredProgram", cascade = CascadeType.ALL)
    @JsonBackReference
    private List<Official> officialList;
}

훈련자

@Data
@NoArgsConstructor
@EntityListeners(TrainerAuditListener.class)
@Entity
public class Trainer extends Auditable<String> {

    @ManyToOne
    @JoinColumn(name = "REGISTERED_PROGRAM_ID", nullable = false)
    @JsonManagedReference
    private RegisteredProgram registeredProgram;

    @Type(type = "yes_no")
    private Boolean isDeleted = false;
}

공무원

@Data
@NoArgsConstructor
@EntityListeners(OfficialAuditListener.class)
@Entity
public class Official extends Auditable<String> {

    @ManyToOne
    @JoinColumn(name = "REGISTERED_PROGRAM_ID", nullable = false)
    @JsonManagedReference
    private RegisteredProgram registeredProgram;

    @Type(type = "yes_no")
    private Boolean isDeleted = false;
}

기본적으로 RegisteredProgram, (Trainer-RegisteredProgram, Official-RegisteredProgram) 와 다 대일 관계를 가진 엔티티가 있습니다. 이제 등록 된 프로그램을 id로 가져 오기 위해 이미 내 요구 사항을 충족하는 서비스가 있으며 isDeleted false 로 모든 Trainer만 포함해야합니다 . 아래 서비스를 참조하십시오.Official

서비스

@Override
public RegisteredProgramRequestDto getRegisteredProgramDto(Long id) {
    RegisteredProgram registeredProgram = registeredProgramRepository.getOne(id);
    RegisteredProgramRequestDto registeredProgramRequestDto = programRegistrationMapper
            .registeredProgramToRequestDto(registeredProgram);
    registeredProgramRequestDto.setOfficialDtoList(
            registeredProgramRequestDto.getOfficialDtoList()
                    .stream()
                    .filter(officialDto -> !officialDto.getIsDeleted())
                    .collect(Collectors.toList())
    );
    registeredProgramRequestDto.setTrainerDtoList(
            registeredProgramRequestDto.getTrainerDtoList()
                    .stream()
                    .filter(trainerDto -> !trainerDto.getIsDeleted())
                    .collect(Collectors.toList())
    );
    return registeredProgramRequestDto;
}

지금, 나는 사용하려 @Query하고 @EntityGraph그래서 난 단지 사용하여 원하는 출력을 얻을 수있을 수있는 단일 쿼리를 .

저장소

@Repository
public interface RegisteredProgramRepository extends JpaRepository<RegisteredProgram, Long>, QuerydslPredicateExecutor<RegisteredProgram> {

    @Query("select rp from RegisteredProgram rp join rp.officialList rpos join rp.trainerList rpts where rp.id = :id and rpos.isDeleted = false and rpts.isDeleted = false")
    @EntityGraph(attributePaths = {"officialList", "trainerList"}, type = EntityGraph.EntityGraphType.LOAD)
    RegisteredProgram getByIdNotDeleted(@Param("id") Long id);
}

업데이트 된 서비스

@Override
public RegisteredProgramRequestDto getRegisteredProgramDto(Long id) {
    RegisteredProgram registeredProgram = registeredProgramRepository.getByIdNotDeleted(id);
    return programRegistrationMapper
            .registeredProgramToRequestDto(registeredProgram);
}

그러나 그것을 구현 한 후 아래 오류가 발생합니다.

org.hibernate.loader.MultipleBagFetchException : 여러 백을 동시에 가져올 수 없음 : [com.tesda8.region8.program.registration.model.entities.RegisteredProgram.officialList, com.tesda8.region8.program.registration.model.entities.RegisteredProgram.trainerList ]

이미 유래를 통해 검색과 마주하는 하지만, 난 여전히 제대로 실행하기 위해 내 쿼리를 얻을 수 없습니다. 어떻게 접근해야할지에 대한 아이디어가 있습니까?

2. 해결방안:

해결을위한 일반적인 수정 MultipleBagFetchException은 다음 과 같이 입력 List된 필드를 변경 하는 것 입니다 Set.

...
public class RegisteredProgram extends Auditable<String> {

    @OneToMany(mappedBy = "registeredProgram", cascade = CascadeType.ALL)
    @JsonBackReference
    private Set<Trainer> trainerList = new HashSet<>();

    @OneToMany(mappedBy = "registeredProgram", cascade = CascadeType.ALL)
    @JsonBackReference
    private Set<Official> officialList = new HashSet<>();
    ...
}

자세한 내용은 https://thorben-janssen.com/hibernate-tips-how-to-avoid-hibernates-multiplebagfetchexception/을 참조 하세요.

주 : 대해 기억 equals하고 hashcode대한 Set데이터 구조 및 회피 람 및 절전 함정 ( https://thorben-janssen.com/lombok-hibernate-how-to-avoid-common-pitfalls/ ). '@Data 피하기'주제에주의를 기울이십시오. 해당 조합을 사용하고있는 것으로 보이므로이 조합은 예기치 않은 동작을 일으킬 수 있습니다!

65731343
반응형