findAll, findById의 차이

Lee Seung Jae·2022년 2월 21일
1

토이 프로젝트 관련

JPA 스터디를 하면서 배운 내용을 토대로 하여 Spring Data JPA를 더 유연하게 사용하기 위해 토이프로젝트를 진행했다.

이슈사항이 될 수도 있겠다 싶어서 삽질 아닌 삽질을 하다가 알게된 사실이다.

사실, 계속 궁금했다. 🤔

코드로 보면 아래와 같은 궁금증이었다.

@Test
void findById() {
    memberRepository.save(member);
    Optional<Member> result = memberRepository.findById(1L);

    result.ifPresent(m -> {
        assertThat(m.getName()).isEqualTo("홍길동");
    });
}
@Test
void findAll() {
    memberRepository.save(member);
    List<Member> list = memberRepository.findAll();
    assertThat(list.size()).isEqualTo(0);
}

이렇게 두 메서드 이다.

결과부터 보자면

findById

image

findAll

findAll

결과가 다르다. 아무 sql을 출력해주지 않는다.

이유는 findAll을 하면 해당 테이블에 있는 모든걸 가져와야 하니까 update를 해야한다.

이 트랜잭션 밖에서 무슨일이 벌어져서 해당 테이블에 무슨 변화가 있었는지 모른다.

그래서 실행 전에 update도 발생한다❗

현재 트랜잭션 안에서 벌어진 일도 반영하고 select를 해야 현재 가장 최신 상태의 데이터를 가져오는거니까 동기화를 하는 느낌? 이라고 생각하면 될것같다.

근데 findById는 한건에 대한 데이터고, 그 한 건이 현재 트랜잭션 안에서 변경중인 데이터이다. 그래서 해당 변경 사항은 이미 영속성 컨텍스트가 관리하는 중이었기 때문에 findAll처럼 updateselect가 발생할 필요없이, 영속성 컨텍스트 안에서 캐싱하고 있던 객체를 찾아주기 때문에 updateselect 모두 발생하지 않은것 처럼 보인다. 근데 해당 코드가 테스트가 아니라 일반 애플리케이션 코드였으면 트랜잭션 끝나고 update가 발생한다.

이게 왜 발생한다고 말을 할 수 있냐면 실제로 한 메서드 내의 트랜잭션에서 save를 빼고 다른 트랜잭션에서 save를 해주고 findById만 조회하면 또 잘나오게 된다.

JPA를 사용함에 있어서 트랜잭션 정말 중요하다는걸 또 한번 깨닫는다❗

데이터를 원하는 조건에 맞게 추출하게 로직을 구현하는건 중요하지만 그 전에 트랜잭션 관리가 최우선이다. 앞으로 더 참고해서 개발해보도록 하자 😁

profile
💻 많이 짜보고 많이 경험해보자 https://lsj8367.tistory.com/ 블로그 주소 옮김

0개의 댓글