작성
·
50
0
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.
1. 강의 내용과 관련된 질문을 남겨주세요.
2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.
(자주 하는 질문 링크: https://bit.ly/3fX6ygx)
3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.
(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)
질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.
=========================================
[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예)
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (아니오)
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)
[질문 내용]
Member member = new Member(1L, "member");
em.persist(member);
member.setName("Test");
tx.commit();
위 코드를 실행하면 아래와 같이 SQL 쿼리문이 로그에 찍히는데요
Hibernate:
/* insert for
hellojpa.Member */
insert
into
Member (name, id)
values
(?, ?)
Hibernate:
/* update
for hellojpa.Member */
update Member
set
name=?
where
id=?
persist()를 할 때 member 객체를 영속성 컨텍스트에 등록하고, 해당 상태에서는 신규 엔티티이므로 setName()으로 이름을 바꾸더라도 새로운 값이고, DB와 동기화되지 않았기에 스냅샷도 없을 것이라 생각했습니다.
저의 [다른 질문](https://www.inflearn.com/community/questions/1484678)에서도 강사님께서 persist 시에는 새로운 데이터이기 때문에 스냅샷 생성의 실익이 없다고 말씀을 해주셨기에, 위 코드에서 INSERT 쿼리문 1개만 발생할 줄 알았는데, 실행 결과 UPDATE 쿼리문도 함께 발생한 것을 확인했습니다.
persist를 수행한 이후 setName을 수행할 때, 스냅샷이 생성되지 않은 상태, 스냅샷이 없는 상태에서 어떻게 변경을 감지하여 UPDATE 쿼리문을 작성한 것인지 궁금합니다.
처음에는 PK 생성 전략을 @GeneratedValue(strategy = GenerationType.IDENTITY)
로 해서 INSERT문이 먼저 생성되는 것이 원인인줄 알았지만, SEQUENCE
전략으로 바꿔도 UPDATE 쿼리문이 발생하는 것을 보고 제가 잘못 짚은 것 같았습니다.
이미 [또 다른 질문](https://www.inflearn.com/community/questions/1494485)에서도 비슷한 질문을 한 번 더 남겼는데, 인프런 AI 인턴의 답변에서는 persist() 호출 시에 스냅샷이 생성이 된다는 답변을 받아 헷갈려서 한 번 더 질문 남겨봅니다.
Entity Manager를 통해 persist() 호출 시에 스냅샷도 생성이 되는 것일까요?
생성이 되지 않는다면, persist 이후에 호출한 setName()에 대해서 UPDATE문이 발생했는데, 여기서 변경 감지는 어떻게 이뤄졌나요?
답변 1
0
안녕하세요, 인프런 AI 인턴입니다. 천다인님.
문의해주신 내용은 JPA의 영속성 컨텍스트와 변경 감지 메커니즘에 대한 깊은 이해가 필요한 부분입니다. 먼저, em.persist()
는 객체를 영속성 컨텍스트에 등록하고 ‘쓰기 지연’ 메커니즘에 의해 INSERT SQL을 준비하게 됩니다. 추가로 객체에 변경이 발생하면 JPA는 기본적으로 변경을 감지하여 변경된 내용을 쿼리로 반영합니다.
영속성 컨텍스트와 스냅샷: em.persist()를 통해 객체가 영속 상태가 되면, JPA는 해당 엔티티의 스냅샷을 생성합니다. 기본적으로 스냅샷은 ‘변경 감지’의 기준으로 사용됩니다.
변경 감지 및 더티 체킹(Dirty Checking): 트랜잭션이 커밋될 때 Flush가 발생하면서 엔티티의 현재 상태와 스냅샷을 비교하여 차이가 있으면 UPDATE SQL이 생성됩니다. 이는 엔티티가 영속성 컨텍스트에 등록될 때만(GENERATION 전략에 관계없이) 발생합니다. 그러므로 setName("Test")
로 값이 변경되었다면, 이 변경 사항이 스냅샷과 다르다고 감지하여 UPDATE 쿼리가 실행된 것입니다.
IDENTITY와 SEQUENCE 전략의 차이: IDENTITY 전략의 경우, 데이터베이스에서 ID가 생성되므로 즉각적인 INSERT가 이루어져야 하는 반면, SEQUENCE 전략은 사용하지 않으니 ID 할당에 지체가 없습니다. 그러나, 둘 다 초기 영속화 시점에 INSERT SQL이 생성됩니다.
유사한 내용에 대한 질문들이 아래 URL에 집약되어 있으니 참고하시기 바랍니다:
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.