inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

[Spring JPA] .save() 대해 문의 드립니다.

해결된 질문

1327

김정훈

작성한 질문수 4

0

4개의 테이블 (a, b, c, d)

각각 1:N 관계 입니다. a-b 1:N, b-c 1:N , c-d 1:N (fetchType = LAZY)

네개의 테이블에 대한 정보를 fetchjoin을 통해서

List<a> 객체로 리턴 받았습니다.

 

List<a> 객체를 루프를 돌면서 a 객체 값에 특정 필드를 변경하고 .save()를 호출 했더니

update 쿼리만 나가는게 아니고

1) a 테이블의 id(pk)값의 조건 select 쿼리 1회

2) b 테이블 조건절에는 id(FK) select 쿼리 1회

3) 위에서 값이 조회될경우 c테이블에 b테이블 결과 id(PK) 값들로 IN 쿼리 1회

4) d 테이블 3)과 동일한 구조로 IN쿼리 1회

5) 최종 udpate 쿼리 호출

이런식의

마치 해당 a 객체 전체 데이터(하위 포함)를 조회 했을떄 날라가는 select쿼리가 모두 호출 되었습니다.

 

예)

List<a> result = aRepository.getFetchJoinQuery();

result.stream().forEach(a -> {

a.setName("HOON");

aRepository.save(a); -> 해당 시점 위 쿼리 호출됨

logger.info("xxxxxx");

});

 

디버깅으로 확인한 내용이구요,

혹시나 디버깅 모드에서 데이터 확인중에 날아간 쿼리인가 해서 디버깅없이 RUN으로

실행했을때도 동일하게 쿼리가 발생하는것이 확인 되었습니다..

 

save() 사용시에 select 쿼리 발생은 어쩔수 없는걸까요?

어쩔수 없다면 save() 메서드 대신 그냥 JPQL로 update 쿼리를 작성해서 사용하는 방법뿐이 없을까요?

궁금합니다!

 

 

 

 

 

김영한 jpa springjpa

답변 1

1

인프런 AI 인턴

안녕하세요, 인프런 AI 인턴입니다.

김정훈님, Spring Data JPA에 있는 .save() 메서드의 작동 방식에 대해 질문해주셨군요. 해당 메서드는 기본적으로 Spring Data JPA의 CrudRepository.save(…)를 사용하여 엔티티를 저장합니다. 만약 엔티티가 새로운 것이 아니라면, 즉 이미 데이터베이스에 존재하는 엔티티라면, Spring Data JPA는 entityManager.merge(…) 메서드를 호출해서 엔티티를 업데이트하게 됩니다. 이 과정에서 엔티티의 현재 상태를 데이터베이스에 있는 상태와 비교하기 위해 추가적인 SELECT 쿼리가 발생할 수 있습니다.

JPA는 엔티티의 상태를 추적하고, 엔티티가 관리 상태가 되면 변경 감지(dirty tracking)을 통해 엔티티의 변경된 부분만 데이터베이스에 반영합니다. 하지만, save()를 호출할 때 JPA가 엔티티의 이전 상태를 알아내기 위해 먼저 조회를 하게 되는 경우도 생길 수 있고, 이는 추가적인 쿼리가 발생하는 원인이 될 수 있습니다.

만약 save() 사용 시 발생하는 SELECT 쿼리가 성능에 문제를 일으키거나 원치 않는 상황이라면, JPQL 또는 @Query 어노테이션을 사용한 업데이트 쿼리를 직접 작성해서 사용하는 방법을 고려하실 수 있습니다. 이 방식을 사용하면 엔티티의 모든 레코드를 조회하지 않고, 필요한 필드만을 대상으로 업데이트 하는 쿼리를 직접 실행시킬 수 있습니다.

자세한 정보는 공식 문서에서 확인하실 수 있습니다.

이와는 다르게 스프링 데이터 JDBC를 사용할 경우, .save() 메서드 작동 방식이 좀 더 단순합니다. 스프링 데이터 JDBC는 엔티티의 이전 상태를 모르고 변경 감지를 하지 않기 때문에 매번 전체 엔티티를 저장할 때 DELETE와 INSERT 쿼리가 발생합니다. 이는 다른 제한 사항을 고려할 때 낭비적일 수 있지만, 스프링 데이터 JDBC의 현재 설계상의 한계입니다.

굳이 모든 데이터를 조회하지 않으려면, 수정이 필요한 필드만을 명시하는 JPQL 업데이트 쿼리 사용이 한 가지 방법이 될 수 있습니다. 단, 이 방법은 영속성 컨텍스트에서 관리되는 엔티티의 상태와 데이터베이스 상태 간에 불일치가 발생할 수 있으므로 주의가 필요합니다.

추가적으로 필요한 내용이나 더 궁금한 점이 있으면 문의해주시기 바랍니다.

0

김정훈

그런 이유에서 였군요.. 매번 자세한 답변 감사드립니다.

서비스에서와 컨트롤러의 @Vaild 적용 차이에 대해서

0

21

2

해결했습니다

0

28

1

지금 강의가 어려우신분 추천드립니다.

0

50

1

기존의 완성된 CRUD의 Build.gradle에 security관련 dependency를 추가하면 문제가 생깁니다.

0

62

2

EmailSender 관련 문의

0

55

1

CRA ? 질문입니다

0

48

1

[해결됨]마지막 강의 내용 수정 화면이 기능을 못하네요.

0

49

1

[해결됨]부분적으로 화면 이동이 안되는 부분이 있습니다.

0

85

6

aws 계정 생성 질문

1

66

1

조회 메서드 네이밍 질문

0

65

1

음성불량

0

49

1

장애 격리 관련해서 궁금한 부분이 있어요

0

56

2

질문있습니다.

0

49

1

코드 깃허브는 없을까요?

1

65

2

핵사고날 아키텍처 기반으로 멀티 모듈 설계 시 질문드립니다..

0

74

2

인넬리제이 무료버전

0

66

2

Post, PostEntity에서 User, UserEntity 의존

0

60

1

내부 객체 직접 접근에 관하여.

0

103

2

CertificationServiceTest

0

56

1

FlushModeType.COMMIT (12:45) 예시코드 질문

0

66

1

readme에 대한 자료는 따로 받아볼수 있나요?

0

99

2

InvalidCurriculumException DIP 적용 여부 문의

0

77

2

Inner class로 Config를 지정하는 이유

0

63

2

Part 2 듣기전 복습하던 중, 아키텍처에 관한 질문이 있습니다.

0

109

2