diff --git a/backend/src/main/java/dev/tripdraw/post/domain/PostRepository.java b/backend/src/main/java/dev/tripdraw/post/domain/PostRepository.java index 7baa16bd..b239b6db 100644 --- a/backend/src/main/java/dev/tripdraw/post/domain/PostRepository.java +++ b/backend/src/main/java/dev/tripdraw/post/domain/PostRepository.java @@ -3,12 +3,12 @@ import static dev.tripdraw.post.exception.PostExceptionType.POST_NOT_FOUND; import dev.tripdraw.post.exception.PostException; +import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; -import java.util.List; - public interface PostRepository extends JpaRepository { @Query("SELECT p FROM Post p JOIN FETCH p.point where p.tripId = :tripId") @@ -19,5 +19,7 @@ default Post getByPostId(Long id) { .orElseThrow(() -> new PostException(POST_NOT_FOUND)); } - void deleteByMemberId(Long memberId); + @Modifying + @Query("DELETE FROM Post p WHERE p.member.id = :memberId") + void deleteByMemberId(@Param(value = "memberId") Long memberId); } diff --git a/backend/src/main/java/dev/tripdraw/trip/application/TripDeleteEventHandler.java b/backend/src/main/java/dev/tripdraw/trip/application/TripDeleteEventHandler.java index c23fbdfb..51f42517 100644 --- a/backend/src/main/java/dev/tripdraw/trip/application/TripDeleteEventHandler.java +++ b/backend/src/main/java/dev/tripdraw/trip/application/TripDeleteEventHandler.java @@ -1,21 +1,24 @@ package dev.tripdraw.trip.application; import dev.tripdraw.member.domain.MemberDeleteEvent; +import dev.tripdraw.trip.domain.PointRepository; import dev.tripdraw.trip.domain.TripRepository; +import java.util.List; +import lombok.RequiredArgsConstructor; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; +@RequiredArgsConstructor @Component public class TripDeleteEventHandler { private final TripRepository tripRepository; - - public TripDeleteEventHandler(TripRepository tripRepository) { - this.tripRepository = tripRepository; - } + private final PointRepository pointRepository; @EventListener public void deletePostByMemberId(MemberDeleteEvent event) { + List tripIds = tripRepository.findAllTripIdsByMemberId(event.memberId()); + pointRepository.deleteByTripIds(tripIds); tripRepository.deleteByMemberId(event.memberId()); } } diff --git a/backend/src/main/java/dev/tripdraw/trip/domain/PointRepository.java b/backend/src/main/java/dev/tripdraw/trip/domain/PointRepository.java index ac4e94e3..aae34c2c 100644 --- a/backend/src/main/java/dev/tripdraw/trip/domain/PointRepository.java +++ b/backend/src/main/java/dev/tripdraw/trip/domain/PointRepository.java @@ -3,7 +3,11 @@ import static dev.tripdraw.trip.exception.TripExceptionType.POINT_NOT_FOUND; import dev.tripdraw.trip.exception.TripException; +import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; public interface PointRepository extends JpaRepository { @@ -11,4 +15,8 @@ default Point getById(Long id) { return findById(id) .orElseThrow(() -> new TripException(POINT_NOT_FOUND)); } + + @Modifying + @Query("DELETE FROM Point p WHERE p.trip.id IN :tripIds") + void deleteByTripIds(@Param(value = "tripIds") List tripIds); } diff --git a/backend/src/main/java/dev/tripdraw/trip/domain/TripRepository.java b/backend/src/main/java/dev/tripdraw/trip/domain/TripRepository.java index edb45c39..86446588 100644 --- a/backend/src/main/java/dev/tripdraw/trip/domain/TripRepository.java +++ b/backend/src/main/java/dev/tripdraw/trip/domain/TripRepository.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -13,7 +14,9 @@ public interface TripRepository extends JpaRepository { List findAllByMemberId(Long memberId); - void deleteByMemberId(Long memberId); + @Modifying + @Query("DELETE FROM Trip t WHERE t.member.id = :memberId") + void deleteByMemberId(@Param(value = "memberId") Long memberId); default Trip getById(Long id) { return findById(id) @@ -27,4 +30,7 @@ default Trip getTripWithPoints(Long tripId) { return findTripWithPoints(tripId) .orElseThrow(() -> new TripException(TRIP_NOT_FOUND)); } + + @Query("SELECT t.id FROM Trip t WHERE t.member.id = :memberId") + List findAllTripIdsByMemberId(@Param(value = "memberId") Long memberId); } diff --git a/backend/src/test/java/dev/tripdraw/member/application/MemberServiceTest.java b/backend/src/test/java/dev/tripdraw/member/application/MemberServiceTest.java index d2a16894..220bbc7f 100644 --- a/backend/src/test/java/dev/tripdraw/member/application/MemberServiceTest.java +++ b/backend/src/test/java/dev/tripdraw/member/application/MemberServiceTest.java @@ -50,7 +50,7 @@ void setUp() { member = memberRepository.save(new Member("통후추", "kakaoId", KAKAO)); trip = tripRepository.save(new Trip(TripName.from("통후추의 여행"), member)); Point point = new Point(3.14, 5.25, LocalDateTime.now()); - trip.add(point); + point.setTrip(trip); postRepository.save(new Post( "제목", point, diff --git a/backend/src/test/java/dev/tripdraw/post/domain/PostRepositoryTest.java b/backend/src/test/java/dev/tripdraw/post/domain/PostRepositoryTest.java index d6d3b6c2..e6dc7ddd 100644 --- a/backend/src/test/java/dev/tripdraw/post/domain/PostRepositoryTest.java +++ b/backend/src/test/java/dev/tripdraw/post/domain/PostRepositoryTest.java @@ -71,13 +71,13 @@ void setUp() { void 회원_ID로_감상을_삭제한다() { // given Post post = new Post("제목", point, "위치", "오늘은 날씨가 좋네요.", member, trip.id()); - postRepository.save(post); + Long postId = postRepository.save(post).id(); // when postRepository.deleteByMemberId(member.id()); // then - assertThat(postRepository.findById(post.id())).isEmpty(); + assertThat(postRepository.existsById(postId)).isFalse(); } @Test diff --git a/backend/src/test/java/dev/tripdraw/trip/application/TripDeleteEventHandlerTest.java b/backend/src/test/java/dev/tripdraw/trip/application/TripDeleteEventHandlerTest.java index 5ac2d23b..88d35cf3 100644 --- a/backend/src/test/java/dev/tripdraw/trip/application/TripDeleteEventHandlerTest.java +++ b/backend/src/test/java/dev/tripdraw/trip/application/TripDeleteEventHandlerTest.java @@ -1,10 +1,13 @@ package dev.tripdraw.trip.application; +import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.then; import static org.mockito.Mockito.times; import dev.tripdraw.member.domain.MemberDeleteEvent; +import dev.tripdraw.trip.domain.PointRepository; import dev.tripdraw.trip.domain.TripRepository; +import java.util.List; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; @@ -21,6 +24,9 @@ class TripDeleteEventHandlerTest { @Mock private TripRepository tripRepository; + @Mock + private PointRepository pointRepository; + @InjectMocks private TripDeleteEventHandler tripDeleteEventHandler; @@ -29,6 +35,10 @@ class TripDeleteEventHandlerTest { // given MemberDeleteEvent memberDeleteEvent = new MemberDeleteEvent(1L); + List tripIds = List.of(1L); + given(tripRepository.findAllTripIdsByMemberId(memberDeleteEvent.memberId())) + .willReturn(tripIds); + // when tripDeleteEventHandler.deletePostByMemberId(memberDeleteEvent); @@ -36,5 +46,8 @@ class TripDeleteEventHandlerTest { then(tripRepository) .should(times(1)) .deleteByMemberId(1L); + then(pointRepository) + .should(times(1)) + .deleteByTripIds(tripIds); } } diff --git a/backend/src/test/java/dev/tripdraw/trip/domain/PointRepositoryTest.java b/backend/src/test/java/dev/tripdraw/trip/domain/PointRepositoryTest.java index ea3da051..5fff89f8 100644 --- a/backend/src/test/java/dev/tripdraw/trip/domain/PointRepositoryTest.java +++ b/backend/src/test/java/dev/tripdraw/trip/domain/PointRepositoryTest.java @@ -4,6 +4,7 @@ import static dev.tripdraw.trip.exception.TripExceptionType.POINT_NOT_FOUND; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.SoftAssertions.assertSoftly; import static org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace.NONE; import dev.tripdraw.common.config.JpaConfig; @@ -12,6 +13,7 @@ import dev.tripdraw.member.domain.MemberRepository; import dev.tripdraw.trip.exception.TripException; import java.time.LocalDateTime; +import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; @@ -37,19 +39,22 @@ class PointRepositoryTest { @Autowired private MemberRepository memberRepository; - private Trip trip; + private Trip huchuTrip; + private Trip herbTrip; @BeforeEach void setUp() { - Member member = memberRepository.save(new Member("통후추", "kakaoId", KAKAO)); - trip = tripRepository.save(Trip.from(member)); + Member huchu = memberRepository.save(new Member("후추", "kakaoId", KAKAO)); + Member herb = memberRepository.save(new Member("허브", "kakaoId", KAKAO)); + huchuTrip = tripRepository.save(Trip.from(huchu)); + herbTrip = tripRepository.save(Trip.from(herb)); } @Test void 위치정보_ID로_위치정보를_조회한다() { // given Point point = new Point(3.14, 5.25, LocalDateTime.now()); - point.setTrip(trip); + point.setTrip(huchuTrip); pointRepository.save(point); // when @@ -69,4 +74,36 @@ void setUp() { .isInstanceOf(TripException.class) .hasMessage(POINT_NOT_FOUND.message()); } + + @Test + void 여행_ID_목록으로_위치정보를_삭제한다() { + // given + Point huchuFirstPoint = new Point(3.14, 5.25, LocalDateTime.now()); + huchuFirstPoint.setTrip(huchuTrip); + Point huchuSecondPoint = new Point(3.14, 5.25, LocalDateTime.now()); + huchuSecondPoint.setTrip(huchuTrip); + + Point herbFirstPoint = new Point(3.14, 5.25, LocalDateTime.now()); + herbFirstPoint.setTrip(herbTrip); + Point herbSecondPoint = new Point(3.14, 5.25, LocalDateTime.now()); + herbSecondPoint.setTrip(herbTrip); + + pointRepository.save(huchuFirstPoint); + pointRepository.save(huchuSecondPoint); + pointRepository.save(herbFirstPoint); + pointRepository.save(herbSecondPoint); + + List tripIds = List.of(huchuTrip.id(), herbTrip.id()); + + // when + pointRepository.deleteByTripIds(tripIds); + + // then + assertSoftly(softly -> { + softly.assertThat(pointRepository.existsById(huchuFirstPoint.id())).isFalse(); + softly.assertThat(pointRepository.existsById(huchuSecondPoint.id())).isFalse(); + softly.assertThat(pointRepository.existsById(herbFirstPoint.id())).isFalse(); + softly.assertThat(pointRepository.existsById(herbSecondPoint.id())).isFalse(); + }); + } } diff --git a/backend/src/test/java/dev/tripdraw/trip/domain/TripRepositoryTest.java b/backend/src/test/java/dev/tripdraw/trip/domain/TripRepositoryTest.java index a062430a..0428aa35 100644 --- a/backend/src/test/java/dev/tripdraw/trip/domain/TripRepositoryTest.java +++ b/backend/src/test/java/dev/tripdraw/trip/domain/TripRepositoryTest.java @@ -14,6 +14,7 @@ import dev.tripdraw.trip.exception.TripException; import java.time.LocalDateTime; import java.util.List; +import java.util.stream.IntStream; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; @@ -98,7 +99,7 @@ void setUp() { tripRepository.deleteByMemberId(member.id()); // then - assertThat(tripRepository.findById(trip.id())).isEmpty(); + assertThat(tripRepository.existsById(trip.id())).isFalse(); } @Test @@ -123,4 +124,18 @@ void setUp() { .isInstanceOf(TripException.class) .hasMessage(TRIP_NOT_FOUND.message()); } + + @Test + void 회원_ID를_갖는_모든_여행_ID를_조회한다() { + // given + List tripIds = IntStream.range(0, 5) + .mapToObj(value -> tripRepository.save(Trip.from(member)).id()) + .toList(); + + // when + List foundIds = tripRepository.findAllTripIdsByMemberId(member.id()); + + // then + assertThat(foundIds).isEqualTo(tripIds); + } }