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

작성자 없음

작성자 정보가 삭제된 글입니다.

실전! 스프링 데이터 JPA

벌크성 수정 쿼리

질문드립니다!

해결된 질문

작성

·

38

0

학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.

1. 강의 내용과 관련된 질문을 남겨주세요.
2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.
(자주 하는 질문 링크: https://bit.ly/3fX6ygx)
3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.
(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)

질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.
=========================================
[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예/아니오)
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)

[질문 내용]@Test void bulkAgePlus(){ memberRepository.save(new Member("AAA", 10, null)); memberRepository.save(new Member("BBB", 15, null)); memberRepository.save(new Member("CCC", 20, null)); memberRepository.save(new Member("DDD", 25, null)); memberRepository.save(new Member("EEE", 30, null)); int count = memberRepository.bulkAgePlus(18); em.flush(); em.clear(); List<Member> result = memberRepository.findByUsername("EEE"); Member findMember = result.get(0); assertThat(count).isEqualTo(3); assertThat(findMember.getAge()).isEqualTo(31); }

여기서 벌크성 연산을 할경우 엔티티 매니저를 거치지 않고 바로 업데이트를 하기에 findById 호출 전에 flush, clear하지 않으면 업데이트 이전에 save된 값이 나오는 것으로 알고 있어(캐쉬된 값) flush, clear를 해주는 것으로 알고 있는데 이때 em.flush()를 해버리면 벌크 연산 값이 아닌 그 이전 값이(save에서 저장한 값 EEE라 가정하면 31이 아닌 30) db에 업데이트 되는 꼴이라 벌크성 연산이 db에 유효하게 저장되려면 em.clear()만 실행 해야되는거 아닌가요?

답변 2

0

안녕하세요. 염경호님, 공식 서포터즈 y2gcoder입니다.

위의 코드는 ID 생성 전략이 무엇인가에 따라 다르게 답변드릴 수 있을 것 같습니다.

  • IDENTITY 전략: 엔티티가 영속성 컨텍스트에 저장되는 시점에 즉시 DB에 INSERT 쿼리를 보내어 ID 값을 생성하고, 그 값을 영속성 컨텍스트에서 사용할 수 있게 합니다. 따라서 flush() 호출 없이도 save한 엔티티가 DB에 반영됩니다.

  • SEQUENCE나 TABLE 같은 다른 전략들: 엔티티가 영속성 컨텍스트에 저장되어도 ID가 미리 할당되기 때문에, DB에 INSERT 쿼리가 즉시 실행되지 않습니다. 이 경우에는 flush()를 호출하여 영속성 컨텍스트에 있는 변경 사항을 DB에 반영해야 합니다. flush()가 호출되지 않으면 save한 엔티티가 DB에 저장되지 않은 상태가 됩니다.

     

 

감사합니다.

0

안녕하세요, 인프런 AI 인턴입니다. 염경호님!

벌크 연산에 대한 질문 주셔서 감사합니다. 벌크 연산은 JPA에서 영속성 컨텍스트를 무시하고 직접 데이터베이스에 영향을 주는 연산입니다. 그렇기 때문에 벌크 연산 후에는 영속성 컨텍스트와 데이터베이스 간의 불일치를 해결하기 위해 추가적인 조치가 필요합니다.

문제의 핵심 포인트:

  • em.flush(): 현재 영속성 컨텍스트에 있는 변경 사항들을 데이터베이스에 반영합니다. 이것은 벌크 연산이 수행되기 전에 영속성 컨텍스트의 상태를 반영하기 위한 과정입니다.
  • em.clear(): 영속성 컨텍스트를 초기화하여 이후 조회되는 데이터가 데이터베이스에서 새롭게 가져온 정보가 되도록 유도합니다.

상세 설명:

  • 벌크 연산을 수행하면 해당 영역의 데이터를 직접 수정합니다. 따라서 벌크 연산 후 em.clear()를 통해 영속성 컨텍스트를 초기화하는 것이 필수입니다. 이렇게 하지 않으면 이전의 영속성 컨텍스트에 저장된 상태가 유지됩니다.
  • em.flush()는 일반적으로 벌크 연산보다 앞서 실행됩니다. 이는 벌크 연산이 실행되기 전에 영속성 컨텍스트의 변경 상태를 데이터베이스에 반영하기 위해 사용됩니다. 이로 인해 불일치를 방지할 수 있습니다.

기존 질문과 유사한 상황 살펴보기:

  • 비슷한 질문이 여기에서 논의된 바 있습니다. 벌크 연산 후의 데이터 반영 및 영속성 컨텍스트 초기화 방법에 대한 유용한 정보가 제공됩니다.

이해하시기 쉽도록 최대한 단순화하여 설명드렸습니다. 이후에도 궁금한 점이 있으시다면 언제든지 추가로 질문해 주세요. 곧 지식공유자님께서 더 구체적인 답변을 드리실 것입니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

작성자 없음

작성자 정보가 삭제된 글입니다.

질문하기