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

dmalk k님의 프로필 이미지
dmalk k

작성한 질문수

실전! 스프링 데이터 JPA

벌크성 수정 쿼리

업데이트가 아닌 delete쿼리를 날리면

작성

·

465

·

수정됨

0

영속성 컨텍스트가 반영 안되게 쿼리를 먼저 날려서 DB에만 반영되고 영속성 컨텍스트는 더티체킹을 못해서 반영이 안되었다고 이해했는데요

 

나이 업데이트 코드가 아니라 멤버를 저장 후에 바로 멤버 하나를 삭제하는 쿼리를 실하면 DB에는 멤버가 삭제되고 영속성 컨텍스트에는 반영안되어서 삭제한 멤버가 조회될 줄 알았는데 조회가 안되더라고요

 

스크린샷 2023-12-21 오전 10.01.18.pngdeleteMemberByUsername메소드가 사용한 쿼리구요

스크린샷 2023-12-21 오전 10.02.17.png테스트 코드 입니다.

 멤버를 테스트 코드 내에서 저장하고, member5를 삭제하고 조회를 해보았습니다.

delete문을 실행하면 update와는 다르게 테이블의 구조가 변경되는 쿼리문이여서 영속성 컨텍스트에서 더티 체킹을 하는 걸까요?

답변 3

0

삭제 쿼리 후,findById(삭제된 멤버 아이디)를 통해 멤버를 조회하면 영속성 컨텍스트에 삭제된 멤버가 남아있는 것을 확인하실 수 있습니다.

0

안녕하세요. dmalk k님, 공식 서포터즈 y2gcoder입니다. AI 답변에 더하여 답변 드립니다.

findByUsername()은 내부적으로 JPQL을 사용하고 JPQL을 날리기 전에 flush를 자동으로 호출하게 됩니다!

이러한 부분을 이해하시면 테스트 코드 결과가 이해가 되실 것 같습니다!
인프런 AI 인턴이 추천해준 링크들도 참고해보시면 좋을 것 같습니다 🙂

감사합니다.

dmalk k님의 프로필 이미지
dmalk k
질문자

JPQL을 날리기 전에 flush를 하면 DB에는 반영이 되고 영속성에는 반영이 안돼야 하는데, Update문은 DB에만 반영되고 영속성에는 반영이 안되고, Delete문은 왜 DB에도 반영되고 영속성 컨텍스트에도 반영이 되는 건가요?

제가 잘못 대답해드린 것 같습니다. 죄송합니다!

혹시 괜찮으시다면 제가 코드를 확인해보고 싶습니다!

실제 동작하는 전체 프로젝트를 압축해서 구글 드라이브로 공유해서 링크를 남겨주세요.

구글 드라이브 업로드 방법은 다음을 참고해주세요.

https://bit.ly/3fX6ygx


주의: 업로드시 링크에 있는 권한 문제 꼭 확인해주세요


추가로 다음 내용도 코멘트 부탁드립니다.

1. 문제 영역을 실행할 수 있는 방법

2. 문제가 어떻게 나타나는지에 대한 상세한 설명


링크: 공식 서포터즈

링크: 자주하는 질문

감사합니다.

 

dmalk k님의 프로필 이미지
dmalk k
질문자

https://drive.google.com/file/d/1JdEff4WAJsEUn9sJX2VePTeGa6yo2Ry3/view?usp=sharing

MemberRepositoryTest에서 258번줄 테스트 코드와

MemberRepository 59번줄에서 delete 쿼리 메소드를 작성했습니다

image권한도 부탁드리겠습니다!

보내주신 코드 잘 살펴보았습니다!

잘 작성해주셨고, 캡처해주신 그대로 테스트 코드가 되어있었습니다.

결론부터 말씀드리자면 DB 조회했을 때 데이터가 있느냐를 기준으로 처리가 달라졌다고 볼 수 있을 것 같습니다.

벌크성 수정 쿼리나 벌크성 삭제 쿼리 모두 영속성 컨텍스트에 반영하지 않고 바로 DB에 직접적으로 결과를 반영하는 것은 맞습니다.

또한 JPQL을 사용했을 시 DB로 쿼리를 날려 조회해오는 것 또한 맞습니다.

그 후에 JPQL을 통해 가져온 데이터를 처리하는 과정에서 결과 차이가 발생한 것 같습니다.

  • 수정 쿼리: 영속성 컨텍스트에 기존 member5가 존재하고 DB 조회 결과로 조회해온 member5가 존재합니다. 영속성 컨텍스트는 @Id가 붙은 필드를 기준으로 엔티티를 관리합니다. 그리고 벌크성 수정 쿼리 특성상 영속성 컨텍스트를 거치지 않고 바로 DB에 반영했기 때문에, JPA 입장에서는 변경된 사실을 모릅니다. 기본적으로 영속성 컨텍스트에 DB 에서 조회해온 member5와 동일한 id를 가진 수정 전의 member5가 있기 때문에, JPA는 DB에서 조회해온 결과를 버리고 영속성 컨텍스트에 있는 member5를 사용합니다. 그래서 변경 내용이 반영되지 않았습니다.

  • 삭제 쿼리: 영속성 컨텍스트에 기존 member5가 존재하고 DB 조회 결과 데이터가 존재하지 않습니다. 영속성 컨텍스트에는 member5가 존재하지만 JPQL로 DB에서 조회한 결과 해당 id를 가진 엔티티가 존재하지 않으므로 JPA는 영속성 컨텍스트의 member5도 삭제하게 됩니다. 그래서 마치 삭제시에는 더티체킹한 것처럼 해당 엔티티가 삭제된 것처럼 결과가 나오게 되었습니다.

     

dmalk k님의 프로필 이미지
dmalk k
질문자

그러면

update는 DB나 영속성 컨텍스트에서나 member5가 있다고 판단되어서, DB는 변경, 영속성은 자기가 가진 member5의 40살을 반환하고,

delete는 findByName()에서 나간 flush()로 DB에 member5가 없어지고 영속성 컨텍스트에서 member5가 남아있어서 DB와 영속성 컨텍스트에서 member5의 유무가 차이나서 영속성 컨텍스트를 수정하게 되는건가요?

아닙니다 여기선 delete 와 update 모두 그 자체는 영속성 컨텍스트에 영향을 주지 않고 바로 DB에 반영된 것이고, 그후 select jpql에서 db를 통해 가져온 결과가 있느냐에 따라 테스트 결과가 달라졌다고 이해하시는게 맞습니다!

0

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

영속성 컨텍스트와 관련하여 삭제 쿼리가 반영되는 과정에 대해 궁금하신 것 같습니다. 이와 유사한 질문에 강사님께서 직접 답변해주신 내용이 있어 링크를 공유드립니다. 참고하시면 도움이 될 것 같습니다.

JPQL을 호출할 때는 항상 flush가 호출됩니다.

쿼리 호출 시 플러시가 자동으로 호출되어 insert 쿼리가 실행됩니다.

JPQL 실행 시 관련 있는 엔티티만 플러시하는 최적화 기능

각 링크에는 JPQL 실행 시 flush가 이루어지는 상황과 해당 쿼리와 관련 있는 엔티티에 대한 플러시 최적화에 대한 설명이 포함되어 있습니다. 질문하신 내용과 밀접하게 관련 있으니, 해당 내용을 확인해보시면 도움이 될 것입니다.

dmalk k님의 프로필 이미지
dmalk k

작성한 질문수

질문하기