JPA 알뜰신잡 1
JPA의 동작에 관하여
JPA 알뜰신잡 1
JPA의 1차 캐시에 대해서
Saga-Orchestrator를 개발하면서 결제가 완료되면 재고 예약을 각 주문 상품별로 진행하게 된다. 이 과정에서 모든 재고 예약이 완료되면 Saga의 상태를 업데이트하게 되는데 이 과정에서 JPA의 동작에 대해서 새로 알게된 점을 간단하게 정리하려고 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
SagaStepEntity sagaStep = sagaStepJpaRepository.findById(event.stepId())
.orElseThrow(() -> new IllegalStateException("Saga step not found"));
sagaStep.setStatus(SagaStepEntity.StepStatus.DONE);
List<SagaStepEntity> inventoryReserveStep = sagaStepJpaRepository
.findBySagaInstanceIdAndStepName(sagaId, "inventoryReserve");
boolean allSuccess = inventoryReserveStep.stream()
.allMatch(step -> step.getStatus() == SagaStepEntity.StepStatus.DONE);
if(allSuccess){
...
}
}
위 코드를 보면 하나의 트랜잭션에서 각 step의 상태를 업데이트하지만 ‘마지막에 업데이트 되는 step이 업데이트 되더라도 findBySagaInstanceIdAndStepName에서 조회 할 때는 아직 transaction이 커밋되지 않았으니 allSuccess는 true가 될 수 없지 않을까?’에 대한 의문을 가지고 있었다.
결과적으로는 ‘아니다’
JPQL 실행 시 흐름
- JPQL → SQL 변환 → DB에 쿼리 전송
- DB에서 ResultSet을 반환
- JPA가 결과를 엔티티로 매핑하려고 할 때
- 각 row의 PK를 기준으로 1차 캐시에 있는지 먼저 확인
- 있으면: 기존 인스턴스 사용 (== 같음)
- 없으면: 새 객체를 생성하고 1차 캐시에 등록
즉, DB 쿼리는 날렸지만, 결과를 엔티티로 변환하는 시점에 1차 캐시가 먼저 참조.
핵심 포인트
✅ 조회 “완료 후”가 아니라 “조회 결과를 엔티티로 매핑할 때” 1차 캐시가 작동합니다.
이 때문에: 같은 트랜잭션 안에서 조건이 달라도 같은 PK를 가진 엔티티는 결국 1차 캐시에 있던 객체를 재사용.
This post is licensed under CC BY 4.0 by the author.