강의

멘토링

로드맵

Inflearn brand logo image

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

재우양님의 프로필 이미지
재우양

작성한 질문수

실전! 스프링 데이터 JPA

벌크성 수정 쿼리

bulk연산 후 flush하는 이유를 모르겠어요

작성

·

51

·

수정됨

0

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

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

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

[질문 내용]
안녕하세요 bulk연산을 하면 영속성 컨텍스트의 내용을 flush하는 동시에 영속성 컨텍스트의 내용을 변경하지 않고 DB에서 값을 변경해버려서 1차 캐시와 데이터가 다르게 된다고 이해했습니다.

그렇다면 bulk연산 할 때 기존에 1차캐시 값들을 flush한다고 이해를 했습니다. 그런데 저희 코드에서 벌크한 뒤에 flush와 clear를 해주는데 clear만 해주면 되는 것 아닌가요?

답변 3

0

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. 재우양님

플러시를 하지 않으면 영속성 컨텍스트에 존재하는 내용이 DB에 반영되지 않습니다.

예를 들어서 회원A의 나이를 19 -> 20로 JPA 엔티티에서 변경했습니다. 이때 플러시를 하지 않으면 변경 감지가 발생하지 않아서 회원의 나이는 애플리케이션에서는 20, DB에는 19인 상태로 남아있습니다.

이때 벌크연산으로 회원이 나이가 20세 이상인 모든 회원을 40세로 변경한다고 하면 어떻게 될까요?

벌크연산은 DB에 직접 수행하는 것입니다. 따라서 회원A의 값은 변경되지 않겠지요?

그래서 영속성 컨텍스트에 있는 변경 내용을 먼저 모두 DB에 반영한 다음에 벌크 연산을 수행해야 합니다.

 감사합니다.

0

재우양님의 프로필 이미지
재우양
질문자

그렇다면 member의 나이를 40에서 41으로 bulk로 업데이트 한 뒤 clear하기 전에 member의 나이를 set명령어를 통해서 +2살로 바뀐다면 최종적으로 43살을 기대하는데 42살로 변경될수 있다는 문제점이 존재하는 건가요?

List<Member> result = memberRepository.findByUsername("user5"); Member member5 = result.get(0); // when int resultCount = memberRepository.bulkAgePlus(20); int age = member5.getAge(); member5.setAge(age + 2); em.flush(); // 변경되지 않은것들 반영해줌 em.clear(); // 영속성 컨텍스트 비우기

0

안녕하세요, 인프런 AI 인턴입니다. 재우양님.

벌크 연산 후 flush()clear()를 사용하는 이유에 대해 설명드리겠습니다.

1. 벌크 연산의 특성:
벌크 연산은 SQL 쿼리로 직접 데이터베이스에 적용되기 때문에 영속성 컨텍스트의 상태를 무시합니다. 이 때문에 영속성 컨텍스트와 데이터베이스 간의 불일치가 발생할 수 있습니다. 벌크 연산 후에도 영속성 컨텍스트에는 이전 상태의 엔티티가 남아 있기에, 불일치를 해소하기 위해 추가 조치가 필요합니다.

2. flush()의 역할:
flush()는 영속성 컨텍스트의 변경 내용을 강제로 데이터베이스에 반영합니다. 벌크 연산 이전에 영속성 컨텍스트에 남아 있는 변경 내역을 데이터베이스와 동기화해야 하는 경우에 flush()를 사용하여 데이터베이스에 안전하게 반영합니다.

3. clear()의 역할:
clear()는 영속성 컨텍스트를 초기화하여, 더 이상 불일치 상태인 데이터에 접근하지 않도록 합니다. 벌크 연산 후 영속성 컨텍스트를 초기화하지 않으면, 이후에 조회한 엔티티는 여전히 이전 상태로 남아 있을 수 있기 때문에, 새로운 데이터베이스 상태를 반영하려면 clear()를 통해 영속성 컨텍스트를 비워주어야 합니다.

결론적으로, flush()clear()를 함께 사용하는 것은 안전한 코딩 습관 입니다. 현재 코드의 안전성과 데이터 일관성을 유지하는 차원에서 권장되는 방식입니다. 다만, 코드의 실행 흐름 상 불필요한 flush()가 있을 경우, 성능상의 이유로 생략할 수도 있으나, 벌크 연산 후 데이터 일관성을 보장하기 위해 flush()clear()를 사용하여 데이터 일관성을 유지하는 것이 일반적입니다.

관련 질문과 답변을 더 참고하시려면 아래의 답변을 확인해 보세요:
- 벌크 수정 연산후 flush clear
- 벌크 연산 수행후 flush( ) 사용 질문

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

재우양님의 프로필 이미지
재우양

작성한 질문수

질문하기