diff --git a/service/src/main/kotlin/com/sangdol/roomescape/reservation/business/ReservationService.kt b/service/src/main/kotlin/com/sangdol/roomescape/reservation/business/ReservationService.kt index 498b6ced..61587cde 100644 --- a/service/src/main/kotlin/com/sangdol/roomescape/reservation/business/ReservationService.kt +++ b/service/src/main/kotlin/com/sangdol/roomescape/reservation/business/ReservationService.kt @@ -154,7 +154,7 @@ class ReservationService( } private fun validateCanCreate(request: PendingReservationCreateRequest) { - val schedule = scheduleService.findSummaryById(request.scheduleId) + val schedule = scheduleService.findSummaryWithLock(request.scheduleId) val theme = themeService.findInfoById(schedule.themeId) reservationValidator.validateCanCreate(schedule, theme, request) diff --git a/service/src/main/kotlin/com/sangdol/roomescape/schedule/business/ScheduleService.kt b/service/src/main/kotlin/com/sangdol/roomescape/schedule/business/ScheduleService.kt index 02325f72..91b4e2dc 100644 --- a/service/src/main/kotlin/com/sangdol/roomescape/schedule/business/ScheduleService.kt +++ b/service/src/main/kotlin/com/sangdol/roomescape/schedule/business/ScheduleService.kt @@ -174,10 +174,16 @@ class ScheduleService( // Other-Service (API 없이 다른 서비스에서 호출) // ======================================== @Transactional(readOnly = true) - fun findSummaryById(id: Long): ScheduleSummaryResponse { + fun findSummaryWithLock(id: Long): ScheduleSummaryResponse { log.info { "[ScheduleService.findDateTimeById] 일정 개요 조회 시작 : id=$id" } - return findOrThrow(id).toSummaryResponse() + val schedule: ScheduleEntity = scheduleRepository.findByIdForUpdate(id) + ?: run { + log.warn { "[ScheduleService.updateSchedule] 일정 조회 실패. id=$id" } + throw ScheduleException(ScheduleErrorCode.SCHEDULE_NOT_FOUND) + } + + return schedule.toSummaryResponse() .also { log.info { "[ScheduleService.findDateTimeById] 일정 개요 조회 완료: id=$id" } } diff --git a/service/src/main/kotlin/com/sangdol/roomescape/schedule/infrastructure/persistence/ScheduleRepository.kt b/service/src/main/kotlin/com/sangdol/roomescape/schedule/infrastructure/persistence/ScheduleRepository.kt index ab70893e..a30fbbed 100644 --- a/service/src/main/kotlin/com/sangdol/roomescape/schedule/infrastructure/persistence/ScheduleRepository.kt +++ b/service/src/main/kotlin/com/sangdol/roomescape/schedule/infrastructure/persistence/ScheduleRepository.kt @@ -1,7 +1,9 @@ package com.sangdol.roomescape.schedule.infrastructure.persistence import com.sangdol.roomescape.schedule.business.domain.ScheduleOverview +import jakarta.persistence.LockModeType import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Lock import org.springframework.data.jpa.repository.Modifying import org.springframework.data.jpa.repository.Query import org.springframework.data.repository.query.Param @@ -11,6 +13,17 @@ import java.time.LocalTime interface ScheduleRepository : JpaRepository { + @Lock(value = LockModeType.PESSIMISTIC_WRITE) + @Query(""" + SELECT + s + FROM + ScheduleEntity s + WHERE + s._id = :id + """) + fun findByIdForUpdate(id: Long): ScheduleEntity? + @Query( """ SELECT