select 쿼리가 나가는 이유
섹션 4. 회원 도메인 개발 회원 기능 테스트 강좌 관련 질문입니다.
@Test
public void 회원가입() throws Exception {
// given
Member member = new Member();
member.setName("kim");
// when
Long saveId = memberService.join(member);
// then
assertEquals(member, memberRepository.findOne(saveId));
}위의 코드를 실행시켰을 때, insert문 쿼리가 왜 나가지 않는지는 이해를 했습니다. 하지만 select 쿼리가 왜 나가는지는 궁금합니다.
제가 생각한 흐름을 설명드리면,
memberService의 join 함수를 실행해서 member 객체를 영속화하게 되면 1차 캐시에 해당 데이터가 저장이 될 것이고 동시에 쓰기 지연 SQL 저장소에 insert 쿼리문이 쌓입니다. 이때 쿼리문은 트랜잭션이 커밋되면 DB에 반영이 되지만 테스트 클래스에서는 트랜잭션이 롤백되기 때문에 insert 쿼리가 나가지 않게 됩니다. 이후 findOne 메소드를 실행할 때에는 DB에서 직접 찌르는 것이 아니라 1차 캐시에 저장되어 있기 때문에 1차 캐시에서 데이터를 가져와도 되기 때문에 select문이 나가지 않아도 된다고 생각했는데 실제 실행결과를 보니 select 쿼리문이 나가더군요.. 이유가 궁금합니다
답변 2
0
안녕하세요. constela10님
join() 메서드를 보시면 validateDuplicateMember()를 호출합니다.
이 메서드는 내부에서 findByName을 호출하는데요. 이때 JPQL이 사용됩니다.
JPQL은 영속성 컨텍스트와 무관하게 항상 SQL을 먼저 실행하게 됩니다.
감사합니다.
0
안녕하세요, 인프런 AI 인턴입니다.
constela10님의 질문에 대한 답변입니다.
회원 가입 테스트 과정에서 select 쿼리가 발생하는 주된 이유는 JPA의 동작 방식 때문입니다. JPA를 사용할 때, 객체를 저장하는 join 메소드와 같은 경우 쓰기 지연 SQL 저장소에 insert 쿼리를 쌓고, 트랜잭션이 커밋되는 시점에 해당 쿼리를 데이터베이스에 반영합니다.
하지만 findOne 메소드를 호출할 때, JPA는 해당 엔티티가 1차 캐시에 존재하는지 확인합니다. 1차 캐시에 해당 데이터가 없으면, 데이터베이스에 실제로 해당 데이터가 존재하는지 확인하기 위해 select 쿼리를 발생시킵니다. 테스트 환경에서는 특정 설정(예: @Transactional)에 의해 실제 데이터베이스에 insert가 반영되지 않고 롤백되기 때문에, insert 쿼리는 보이지 않습니다.
테스트 클래스가 기본적으로 트랜잭션을 롤백하는 동작을 수행하기 때문에, insert 쿼리는 실행되지만 실제 데이터베이스에 반영되지 않습니다. 그렇기 때문에 findOne을 호출했을 때, JPA는 이미 영속성 컨텍스트에 해당 엔티티가 있는지 확인 후 없다고 판단하고 데이터베이스에서 직접 조회하기 위해 select 쿼리를 실행하게 됩니다.
이런 동작은 JPA가 보장하는 영속성 컨텍스트 내의 1차 캐시의 일관성을 유지하기 위해 필요한 절차입니다. 만약 join 메소드 실행 시 영속화된 엔티티의 식별자가 데이터베이스에 이미 존재한다면, JPA는 insert가 아닌 select를 먼저 호출하여 해당 식별자의 엔티티가 이미 있는지 검증합니다. 이 과정에서도 select 쿼리가 발생할 수 있습니다.
이 설명이 constela10님의 궁금증을 해결하는데 도움이 되었기를 바랍니다.
OrderServiceTest 상문주문 테스트 시 update 쿼리 문의
0
27
1
sdk 설정 오류
0
68
2
오탈자 - @Transactional
0
63
1
src/test/resources 테스트 경로 문제
0
60
1
상품 등록후 H2 db 출력 순서 바꿀 수 있나요?
0
70
1
MemberRepositoryTest 실행오류
0
90
1
boot 4.x >>> trasasction rolled back log & p6spy(영한님, 수업 자료 업데이트 해주시면 감사하겠습니다!!)
1
197
2
강의 마지막 QueryDSL 사용 부분 질문있습니다
1
154
2
클라이언트에서 isbn과 author 수정 요청을 한 경우에 대해 질문드립니다.
0
57
1
도메인 모델 패턴 vs 트랜잭션 스크립트 패턴
0
80
1
기본 생성자
0
67
1
h2 DB 연결시 jdbc url 변경 이유가 궁금합니다.
0
107
1
멤버서비스테스트 부분에서 막힙니다.
0
174
4
실무에서도 EntityManager를 이용해서 많이 작업하는 편일까요?
0
124
1
초반에 h2 다운로드 과정 꼭 필요한가요?
0
129
2
자신 필드에도 get으로 접근하는 이유가 있을까요?
0
122
1
24분 27초 연관관계 편의 메서드 위치
0
118
1
단건 주문만 가능하게 한건 의도한 부분이신가요?
0
114
2
빌드 툴, Gradle
0
65
1
h2연결은 된 것 같은데 엔티티 테이블까지 작성 후 확인해보아도 테이블이 안보입니다
0
82
2
Repository에서 EntityManager 주입 방식 차이
0
97
1
롬복과 사용자 정의 setter 메서드
0
78
1
주문 목록 조회 fetch join 질문드립니다
0
91
1
dirty checking 질문드립니다.
0
87
1





