개요
- 실제 비즈니스 로직에서의 LazyLoading의 실행흐름에 대해 파악 할 수 있습니다.
사전준비
- Caregiver <-> User <-> Patient
- 현재 3개는 서로 OneToOne관계를 가지고있으며, User Entity에서 옵션을 관리하고있다.
비즈니스 로직
@Transactional
public CareMatchingDetailResponse generate(final AuthUser authUser, final CareMatchingRequestDto dto) {
User user = userQuery.readById(authUser.getUserId());
Patient patient = null;
Caregiver caregiver = null;
if (dto.getUserType().equals(UserType.CAREGIVER)) {
patient = user.getPatient();
caregiver = caregiverQuery.readById(dto.getTargetId());
}
if (dto.getUserType().equals(UserType.PATIENT)) {
patient = patientQuery.readById(dto.getTargetId());
caregiver = user.getCaregiver();
}
CareValidate.validateSelfCareMatching(patient, caregiver);
Boolean isCareMatching = careMatchingQuery.existsByActiveUserInCareMatching(patient, caregiver);
CareValidate.validateCareMatching(isCareMatching);
CareMatching careMatching = CareMatching.of(patient, caregiver, dto);
CareMatching saveCareMatching = careMatchingCommand.create(careMatching);
return CareMatchingDetailResponse.of(saveCareMatching);
}
예상
- dto.getUserType().equals(UserType.CAREGIVER) 의 분기문을 탄다고 가정해보자
- User를 DB에서 찾아온다 (이때 Caregiver,Patient 둘다 프록시 객체로 감싸져있다)
- User안에 있는 Patient를 호출할때, 프록시 객체가 아닌 실제 객체로 바뀐다
실제
User를 DB에서 찾아온다 (이때 Caregiver,Patient 둘다 프록시 객체로 감싸져있다)
실제로도 두객체모두 프록시 객체로 잘 감싸져있는 모습이다.
User안에 있는 Patient를 호출할때, 프록시 객체가 아닌 실제 객체로 바뀐다
실제 객체가 필요하여 호출하였음에도, 아직 프록시 객체로 감싸져 있는 모습이다.
왜 안되지?
- LazyLoading에 대한 개념을 다시한번 정리하고 갈 필요가있다.
- 우리가 Lazy를 걸어둔 Entity에 대해서 실제 그 객체를 사용하기 이전까지는 쿼리가 날라가지 않는다.
- 그리고 쿼리를 날라갔다고해서 인텔리제이상에서 보이는 객체는 여전히 Null로 찍힌다
- 그럼 우리는 필드 접근 -> 프록시 객체 -> 실제 객체를 타고 가는 흐름은 유지가 되는것이지
- 필드 접근 -> 실제 객체를 타고가는 흐름으로 변경되는 것이 아니다
User Entity를 조회하는 쿼리를 봐보자
Hibernate:
select
u1_0.id,
u1_0.auth_provider,
u1_0.caregiver_id,
u1_0.created_at,
u1_0.email,
u1_0.nickname,
u1_0.password,
u1_0.patient_id,
u1_0.phone_number,
u1_0.resident_registration_number,
u1_0.updated_at,
u1_0.user_role,
u1_0.user_wallet_id
from
user u1_0
where
u1_0.id=?
- 매핑되어있는 Caregiver,Patient는 가져오지않고 User객체 단 하나만 가져오는 모습이다
User안의 Patient를 조회할경우?
Hibernate:
select
p1_0.id,
p1_0.created_at,
p1_0.diagnosis,
p1_0.is_visible,
p1_0.location,
p1_0.name,
p1_0.updated_at,
u1_0.id,
u1_0.auth_provider,
u1_0.caregiver_id,
u1_0.created_at,
u1_0.email,
u1_0.nickname,
u1_0.password,
u1_0.patient_id,
u1_0.phone_number,
u1_0.resident_registration_number,
u1_0.updated_at,
u1_0.user_role,
u1_0.user_wallet_id
from
patient p1_0
left join
user u1_0
on u1_0.id=p1_0.user_id
where
p1_0.id=?
- 그때 Lazy가 실행되면서, Patient에 대한 객체를 가져오는 모습을 확인 할 수 있다.
오늘 나는 무엇을 알았는가?
- 프록시 객체에 접근할때 쿼리가 수행된다
- 프록시 객체에대해 쿼리를 수행한후 실제 객체를 가져오더라도, 프록시 객체는 벗겨지는것이 아닌 프록시 객체를 통해 실제 객체를 가져오는 흐름을 유지한다.
'SpringBoot' 카테고리의 다른 글
JPA에서 ID 값이 NULL일 때와 존재할 때, INSERT vs UPDATE의 차이점 (0) | 2025.03.18 |
---|---|
카카오 소셜 로그인시, CORS 문제 발생 (1) | 2025.03.13 |
다양한 상황에서의 DB에 저장하는 시간을 알아보자 (0) | 2025.02.26 |
Redis에 엔티티 저장중 생긴 순환참조문제 (0) | 2025.01.23 |
JSP 란? (1) | 2025.01.21 |