인프런 커뮤니티 질문&답변

Jin Heung An님의 프로필 이미지
Jin Heung An

작성한 질문수

실전! 스프링 데이터 JPA

페치조인과 new 프로젝션

해결된 질문

작성

·

223

·

수정됨

2

Member Entity

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Builder
@AllArgsConstructor
@ToString(of = {"id", "username", "age"})
@NamedQuery(
        name = "Member.findByAgeGreaterThanAndUsername",
        query = "select m from Member m where m.age > :age and m.username = :username"
)
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "member_id")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "team_id")
    private Team team;

    private String username;
    private int age;

    /**
     * 연관관계 편의 메서드
     */
    public void changeTeam(Team team) {
        this.team = team;
        team.getMembers().add(this);
    }
}

 

Team Entity

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Builder
@AllArgsConstructor
@ToString(of = {"id", "name"})
public class Team {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "team_id")
    private Long id;

    @OneToMany(mappedBy = "team", fetch = FetchType.LAZY)
    @Builder.Default
    private List<Member> members = new ArrayList<>();

    private String name;
}

 

MemberRepository

public interface MemberSpringJpaRepository extends JpaRepository<Member, Long> {

    List<Member> findByUsernameAndAgeGreaterThan(String username, int age);

    @Query(name = "Member.findByAgeGreaterThanAndUsername")
    List<Member> findByAgeGreaterThanAndUsername(@Param("age") int age,
                                                 @Param("username") String username);

    @Query(value = "select m from Member m")
    List<Member> findUsers();

    @Query(value = "select new study.datajpa.dto.MemberDto(m.id, m.username, t.name) from Member m join m.team t")
    List<MemberDto> findMemberDtoWithJoin();

    /**
     * fetch join -> new 프로젝션 예외 터짐
     */
//    @Query(value = "select new study.datajpa.dto.MemberDto(m.id, m.username, t.name) from Member m join fetch m.team t")
//    List<MemberDto> findMemberDtoWithFetchJoin();

    @Query(value = "select m from Member m join m.team t")
    List<Member> findMemberJoinWithTeam();
}

 

질문

    /**
     * join -> new 프로젝션 정상 수행
     */
    @Query(value = "select new study.datajpa.dto.MemberDto(m.id, m.username, t.name) from Member m join m.team t")
    List<MemberDto> findMemberDtoWithJoin();

    /**
     * fetch join -> new 프로젝션 예외 터짐
     */
//    @Query(value = "select new study.datajpa.dto.MemberDto(m.id, m.username, t.name) from Member m join fetch m.team t")
//    List<MemberDto> findMemberDtoWithFetchJoin();

@Query 애너테이션에서 쿼리문을 작성할 때, new 연산자를 사용하여 dto로 변환하여 반환하려고 합니다. Member-Team을 join 후 new 연산자를 사용하여 dto는 정상적으로 반환이 됩니다. 근데 페치조인을 사용 후 new 연산자를 사용하면 아래 예외가 터집니다.

fetch join으로는 new 연산자 사용이 안 되는 이유를 알고싶습니다.

 

발생하는 예외

java.lang.IllegalStateException: Failed to load ApplicationContext for [WebMergedContextConfiguration@3d1b6816 testClass = study.datajpa.repository.springjpa.MemberSpringJpaRepositoryTest, locations = [], classes = [study.datajpa.DataJpaApplication], contextInitializerClasses = [], activeProfiles = [], propertySourceDescriptors = [], propertySourceProperties = ["org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true"], contextCustomizers = [org.springframework.boot.test.autoconfigure.actuate.observability.ObservabilityContextCustomizerFactory$DisableObservabilityContextCustomizer@1f, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizer@1255b1d1, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@47da3952, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@28a0fd6c, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@5fb97279, org.springframework.boot.test.context.SpringBootTestAnnotation@3f26d230], resourceBasePath = "src/main/webapp", contextLoader = org.springframework.boot.test.context.SpringBootContextLoader, parent = null]

답변 1

Jin Heung An님의 프로필 이미지
Jin Heung An

작성한 질문수

질문하기