findAll() 메서드

미해결질문
조한선닮은이 프로필

안녕하세요..

우선 다른 질문들에 답변이 없어서 답변이 달릴까 조금 걱정은되는데 질문드려요ㅠ

findAll() 메서드로 fetch 는 default로 하면 lazy로 되더라구요..

ManytoOne 이더라도요..

그 이유가 find all이라서 많은 데이터를 가져오게 되니까  jpa 에서 일부러 그렇게 전략을 짠건지요..?

제가 이해한게 맞는지 확인차 질문 올립니다.

백기선 프로필
백기선 4달 전

"findAll() 메서드로 fetch 는 default로 하면 lazy로 되더라구요.." 이 말씀에 대한 근거는 무엇인가요? 코드로  보여주시겠어요?

백기선 프로필
백기선 4달 전

그리고 다른 질문들에 답변이 없다니요? 제 강좌 질문은 거의 매일 확인하고 답할 수 있는 질문엔 거의 다 답을 달아드리고 있습니다. 혹시 이전에 남기신 어떤 질문에 제가 답을 안드렸다면 링크를 부탁드려요.

조한선닮은이 프로필
조한선닮은이 4달 전

네 답변 주셔서 감사합니다.

먼저 기분나쁘셨다면 사과드릴게요ㅠㅠ 그리고 이 질문이 스프링 데이터 JPA 2. JpaRepository.save() 메소드 이 강의에 되어있는지 잘 모르겠네요 다른데서 질문을 남긴것 같은데ㅠㅠ

아마 스프링 데이터 JPA 7.EntityGraph 강의에 질문을 남겼던것 같습니다... 이 강의의 질문에 보면 3개중에 2개가 답변이 없어서 답변이 잘 안 달리나보다 생각했습니다ㅠㅠ

좋은강의 잘듣고 있어서 감사한데 기분나쁘게 해서 죄송해여ㅠㅠ

제가 3가지를 해봤는데요 ManyToOne으로 fetch 전략을 1)default로 한경우 2)LAZY로 한경우 3)EAGER로 한경우로 해봤습니다.

1)fetch전략을 default로 한경우

 - findAll() : lazy로 동작,  findById() : EAGER로 동작

2)fetch전략을 lazy로 한경우

 - findAll() : lazy로 동작, findById() : lazy로 동작

3)fetch전략을 eager로 한경우

 - findAll() : lazy로 동작, findById() : eager로 동작

아래 코드랑 결과도 작성해 드립니다..

혹시 제가 잘못 설정해서 그런것이 있다면 지적해주시고 알려주시면 감사드리겠습니다.

================코드===================

package com.hong.springjpa4;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Getter
@Setter
@Entity
public class Post {

@Id
@GeneratedValue
private Long id;

private String title;
}


package com.hong.springjpa4;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;

@Entity
@Getter
@Setter
public class Comment {
@Id
@GeneratedValue
private Long id;

private String comment;

// @ManyToOne(fetch = FetchType.EAGER)
@ManyToOne
private Post post;

private int up;

private int down;

private boolean best;

}
package com.hong.springjpa4;

import org.springframework.data.jpa.repository.JpaRepository;

public interface CommentRepository extends JpaRepository<Comment, Long> {
}
package com.hong.springjpa4;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.junit4.SpringRunner;

import static org.junit.Assert.*;

@RunWith(SpringRunner.class)
@DataJpaTest
public class CommentRepositoryTest {
@Autowired
CommentRepository commentRepository;

@Test
public void findTest(){
System.out.println("findAll() ================");
commentRepository.findAll();

System.out.println("findById() ================");
commentRepository.findById(1l);
}
}

================결과===================

1)fetch를 defualt 로 한경우 결과

findAll() ================
Hibernate:
select
comment0_.id as id1_0_,
comment0_.best as best2_0_,
comment0_.comment as comment3_0_,
comment0_.down as down4_0_,
comment0_.post_id as post_id6_0_,
comment0_.up as up5_0_
from
comment comment0_
findById() ================
Hibernate:
select
comment0_.id as id1_0_0_,
comment0_.best as best2_0_0_,
comment0_.comment as comment3_0_0_,
comment0_.down as down4_0_0_,
comment0_.post_id as post_id6_0_0_,
comment0_.up as up5_0_0_,
post1_.id as id1_1_1_,
post1_.title as title2_1_1_
from
comment comment0_
left outer join
post post1_
on comment0_.post_id=post1_.id
where
comment0_.id=?

2)fetch전략을 lazy로 한경우 결과

findAll() ================
Hibernate:
select
comment0_.id as id1_0_,
comment0_.best as best2_0_,
comment0_.comment as comment3_0_,
comment0_.down as down4_0_,
comment0_.post_id as post_id6_0_,
comment0_.up as up5_0_
from
comment comment0_
findById() ================
Hibernate:
select
comment0_.id as id1_0_0_,
comment0_.best as best2_0_0_,
comment0_.comment as comment3_0_0_,
comment0_.down as down4_0_0_,
comment0_.post_id as post_id6_0_0_,
comment0_.up as up5_0_0_
from
comment comment0_
where
comment0_.id=?

3)fetch 전략을 eager로 한경우 결과

findAll() ================
Hibernate:
select
comment0_.id as id1_0_,
comment0_.best as best2_0_,
comment0_.comment as comment3_0_,
comment0_.down as down4_0_,
comment0_.post_id as post_id6_0_,
comment0_.up as up5_0_
from
comment comment0_
findById() ================
Hibernate:
select
comment0_.id as id1_0_0_,
comment0_.best as best2_0_0_,
comment0_.comment as comment3_0_0_,
comment0_.down as down4_0_0_,
comment0_.post_id as post_id6_0_0_,
comment0_.up as up5_0_0_,
post1_.id as id1_1_1_,
post1_.title as title2_1_1_
from
comment comment0_
left outer join
post post1_
on comment0_.post_id=post1_.id
where
comment0_.id=?

백기선 프로필
백기선 4달 전

아 기분이 나쁜게 아니라 제가 놓친 질문들이 있는거 같아서 여쭤본건데 정말 있네요. 다시 둘러보겠습니다. 감사합니다.

그리고 이 질문 정말 좋은 질문입니다. 코드를 통해 발견하신대로, 스프링 데이터 JPA가 제공하는 findAll()은 fetchmode를 적용하지 않습니다.

JPA가 제공하는 EntityManager를 통해 객체를 읽어오면 (findById()) 우리가 설정한 fetchmode가 적용되지만 JPQL을 사용해서 쿼리하면 적용되지 않아요. 그런 경우에는 @EntityGraph나 fetch join을 JPQL 만들 때 사용해야 합니다.

스프링 데이터 JPA가 제공하는 findAll 같은 경우도 JPQL로 쿼리를 만들어 실행하는 경우기 때문에 fetchmode 설정이 반영 안되지만 findById()는 EntityManger가 기본으로 제공하는 find()를 사용해서 읽어오기 때문에 적용이 됩니다. 아쉽게도 EntityManager의 find는 식별자를 사용해서 엔티티 하나만 찾아오는 메소드이고 콜렉션을 찾아오는 기능은 없기 때문에 스프링 데이터 JPA가 구현한대로 JPQL을 사용할 수밖에 없습니다.

감사합니다.

조한선닮은이 프로필
조한선닮은이 3달 전

아 답변감사합니다. jpql을 사용한다니 신기하네요.

궁금한게 있는데요 기선님은 저런내용을 어떻게 아시는거에요? jpa도큐먼트를 보면 나오나요??

혹시 url이있다면 좀 알려주실수 있을까요 ㅎ

저도 나중에 궁금하거나 이해안되는 부분이 있으면 스스로 답을 찾고싶어서 여쭤봅니다 :)

그리고 유투브를 통해 새로운 강의가 나온다고 들었습니다. 기대되네요~ㅎㅎ

지식공유자 되기
많은 사람들에게 배움의 기회를 주고,
경제적 보상을 받아보세요.
지식공유참여
기업 교육을 위한 인프런
“인프런 비즈니스” 를 통해 모든 팀원이 인프런의 강의들을
자유롭게 학습하는 환경을 제공하세요.
인프런 비즈니스