Skip to content

Commit

Permalink
Merge pull request #65 from delicious-algorithme/feature/63-bookmark-…
Browse files Browse the repository at this point in the history
…all-n+1-solve

feature: 북마크, 가게 아이디 조회 API 구현 & N+1 문제 해결
  • Loading branch information
yeoncheong08 authored Nov 25, 2024
2 parents 700113b + e7d7f29 commit 75fd988
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 18 deletions.
14 changes: 7 additions & 7 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ tasks.named('test') {
useJUnitPlatform()
}

processResources.dependsOn('copySecret')

tasks.register('copySecret', Copy) {
from './matal-submodule'
include "application*.yml"
into './src/main/resources'
}
//processResources.dependsOn('copySecret')
//
//tasks.register('copySecret', Copy) {
// from './matal-submodule'
// include "application*.yml"
// into './src/main/resources'
//}

tasks.named("jar") {
enabled = false;
Expand Down
20 changes: 19 additions & 1 deletion src/main/java/matal/bookmark/controller/BookmarkController.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import lombok.RequiredArgsConstructor;
import matal.bookmark.dto.response.BookmarkResponseDto;
import matal.bookmark.dto.response.BookmarkStoreIdsResponseDto;
import matal.bookmark.service.BookmarkService;
import matal.global.auth.LoginMember;
import matal.global.exception.ErrorResponse;
Expand Down Expand Up @@ -51,7 +53,7 @@ public ResponseEntity<Void> createBookmark(
}

@GetMapping
@Operation(summary = "북마크 조회 기능", description = "사용자가 북마크한 가게들을 조회할 때 사용하는 API")
@Operation(summary = "북마크 페이징 조회 기능", description = "사용자가 북마크한 가게들을 10개씩 조회할 때 사용하는 API")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "북마크 조회 성공",
content = {@Content(schema = @Schema(implementation = Void.class))}),
Expand All @@ -67,6 +69,22 @@ public ResponseEntity<Page<BookmarkResponseDto>> getBookmarks(
return ResponseEntity.ok(bookmarkResponse);
}

@GetMapping("/ids")
@Operation(summary = "북마크 IDs 조회 기능", description = "사용자가 북마크한 가게들을 모두 조회할 때 사용하는 API")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "북마크 조회 성공",
content = {@Content(schema = @Schema(implementation = Void.class))}),
@ApiResponse(responseCode = "401", description = "회원 세션 정보 없음",
content = {@Content(schema = @Schema(implementation = ErrorResponse.class))}),
@ApiResponse(responseCode = "404", description = "회원 조회 실패",
content = {@Content(schema = @Schema(implementation = ErrorResponse.class))})})
public ResponseEntity<List<BookmarkStoreIdsResponseDto>> getBookmarkStoreIds(
@LoginMember @Parameter(hidden = true) AuthMember authMember)
{
List<BookmarkStoreIdsResponseDto> bookmarkResponse = bookmarkService.getBookmarkStoreIds(authMember);
return ResponseEntity.ok(bookmarkResponse);
}

@DeleteMapping("/{id}")
@Operation(summary = "북마크 삭제 기능", description = "사용자가 가게를 북마크로 저장할 때 사용하는 API")
@ApiResponses(value = {
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/matal/bookmark/domain/Bookmark.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
Expand Down Expand Up @@ -29,11 +30,11 @@ public class Bookmark extends BaseTimeEntity {
@Column(name = "bookmark_id")
private Long bookmarkId;

@OneToOne
@OneToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "member_id")
private Member member;

@OneToOne
@OneToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "store_id")
private Store store;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
package matal.bookmark.domain.repository;

import java.util.List;
import matal.bookmark.domain.Bookmark;
import matal.bookmark.dto.response.BookmarkStoreIdsResponseDto;
import matal.member.domain.Member;
import matal.store.domain.Store;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.EntityGraph.EntityGraphType;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface BookmarkRepository extends JpaRepository<Bookmark, Long> {

Page<Bookmark> findBookmarksByMemberId(Long id, Pageable pageable);
@EntityGraph(attributePaths = {"store"}, type = EntityGraphType.FETCH)
@Query("SELECT DISTINCT b FROM Bookmark b LEFT JOIN b.store WHERE b.member.id = :memberId")
Page<Bookmark> findBookmarksByMemberId(@Param("memberId") Long id, Pageable pageable);

@Query("SELECT new matal.bookmark.dto.response.BookmarkStoreIdsResponseDto(b.bookmarkId, b.store.storeId) " +
"FROM Bookmark b WHERE b.member.id = :memberId")
List<BookmarkStoreIdsResponseDto> findBookmarkStoreIdsByMemberId(@Param("memberId") Long memberId);


Boolean existsBookmarkByStoreAndMember(Store store, Member member);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package matal.bookmark.dto.response;

public record BookmarkStoreIdsResponseDto(Long bookmarkId,
Long storeId) {
}
8 changes: 8 additions & 0 deletions src/main/java/matal/bookmark/service/BookmarkService.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package matal.bookmark.service;

import java.util.List;
import lombok.RequiredArgsConstructor;
import matal.bookmark.domain.Bookmark;
import matal.bookmark.domain.repository.BookmarkRepository;
import matal.bookmark.dto.response.BookmarkStoreIdsResponseDto;
import matal.bookmark.dto.response.BookmarkResponseDto;
import matal.global.exception.AlreadyExistException;
import matal.global.exception.AuthException;
Expand Down Expand Up @@ -50,6 +52,12 @@ public Page<BookmarkResponseDto> getBookmarks(AuthMember authMember, int page) {
return bookmarkRepository.findBookmarksByMemberId(authMember.memberId(), pageable).map(BookmarkResponseDto::from);
}

@Transactional(readOnly = true)
public List<BookmarkStoreIdsResponseDto> getBookmarkStoreIds(AuthMember authMember) {
validateMember(authMember.memberId());
return bookmarkRepository.findBookmarkStoreIdsByMemberId(authMember.memberId());
}

@Transactional
public void deleteBookmark(AuthMember authMember, Long bookmarkId) {
validateMember(authMember.memberId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
import matal.bookmark.dto.response.BookmarkResponseDto;
import matal.bookmark.dto.response.BookmarkStoreIdsResponseDto;
import matal.bookmark.service.BookmarkService;
import matal.global.exception.AuthException;
import matal.global.exception.NotFoundException;
Expand Down Expand Up @@ -101,8 +102,6 @@ void beforeEach() {
)
)
);

Pageable pageable = PageRequest.of(0, 10);
}

@Test
Expand Down Expand Up @@ -160,7 +159,7 @@ void testCreateBookmarkFailure2() throws Exception {
}

@Test
@DisplayName("북마크 리스트 조회 성공 테스트")
@DisplayName("북마크 페이지 조회 성공 테스트")
void testGetBookmarksSuccess() throws Exception {
// given
Pageable pageable = PageRequest.of(0, 10);
Expand All @@ -182,7 +181,7 @@ void testGetBookmarksSuccess() throws Exception {
}

@Test
@DisplayName("북마크 리스트 조회 시 세션 정보 없음으로 인한 실패 테스트")
@DisplayName("북마크 페이지 조회 시 세션 정보 없음으로 인한 실패 테스트")
void testGetBookmarksFailure() throws Exception {
// given

Expand All @@ -198,7 +197,7 @@ void testGetBookmarksFailure() throws Exception {
}

@Test
@DisplayName("북마크 리스트 조회 시 회원 정보를 찾지 못해 발생하는 실패 테스트")
@DisplayName("북마크 페이지 조회 시 회원 정보를 찾지 못해 발생하는 실패 테스트")
void testGetBookmarksFailure2() throws Exception {
// given

Expand All @@ -214,6 +213,68 @@ void testGetBookmarksFailure2() throws Exception {
.andDo(print());
}

@Test
@DisplayName("북마크, 가게 아이디 조회 성공 테스트")
void testGetBookmarkStoreIdsSuccess() throws Exception {
// given
List<BookmarkStoreIdsResponseDto> bookmarks = List.of(
new BookmarkStoreIdsResponseDto(
1L, 1L
),
new BookmarkStoreIdsResponseDto(
1L, 2L
)
);


// when
when(bookmarkService.getBookmarkStoreIds(mockMember)).thenReturn(bookmarks);

// then
mockMvc.perform(get("/api/bookmarks/ids")
.contentType("application/json")
.session(mockSession))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0].bookmarkId").value(1L))
.andExpect(jsonPath("$[0].storeId").value(1L))
.andExpect(jsonPath("$[1].bookmarkId").value(1L))
.andExpect(jsonPath("$[1].storeId").value(2L))
.andDo(print());
}

@Test
@DisplayName("북마크 가게 아이디 조회 시 세션 정보 없음으로 인한 실패 테스트")
void testGetBookmarkStoreIdsFailure() throws Exception {
// given

// when
when(bookmarkService.getBookmarkStoreIds(mockMember))
.thenThrow(new AuthException(ResponseCode.SESSION_VALUE_EXCEPTION));

// then
mockMvc.perform(get("/api/bookmarks/ids")
.contentType("application/json"))
.andExpect(status().isUnauthorized())
.andDo(print());
}

@Test
@DisplayName("북마크 가게 아이디 조회 시 회원 정보를 찾지 못해 발생하는 실패 테스트")
void testGetBookmarkStoreIdsFailure2() throws Exception {
// given

// when
doThrow(new NotFoundException(ResponseCode.STORE_NOT_FOUND_ID))
.when(bookmarkService).getBookmarkStoreIds(mockMember);

// then
mockMvc.perform(get("/api/bookmarks/ids")
.contentType("application/json")
.session(mockSession))
.andExpect(status().isNotFound())
.andDo(print());
}

@Test
@DisplayName("북마크 삭제 성공 테스트")
void testDelteBookmarkSuccess() throws Exception {
Expand Down
47 changes: 45 additions & 2 deletions src/test/java/matal/bookmark/service/BookmarkServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import matal.bookmark.domain.Bookmark;
import matal.bookmark.domain.repository.BookmarkRepository;
import matal.bookmark.dto.response.BookmarkResponseDto;
import matal.bookmark.dto.response.BookmarkStoreIdsResponseDto;
import matal.global.exception.NotFoundException;
import matal.global.exception.ResponseCode;
import matal.member.domain.Member;
Expand Down Expand Up @@ -154,7 +155,7 @@ void testSaveBookmarkFailure3() {
}

@Test
@DisplayName("북마크 리스트 조회 성공 테스트")
@DisplayName("북마크 페이지 조회 성공 테스트")
void testGetBookmarksSuccess() {
// given
List<Bookmark> bookmarks = List.of(
Expand Down Expand Up @@ -184,7 +185,7 @@ void testGetBookmarksSuccess() {
}

@Test
@DisplayName("북마크 리스트 조회 시 회원 정보 없음으로 인한 실패 테스트")
@DisplayName("북마크 페이지 조회 시 회원 정보 없음으로 인한 실패 테스트")
void testGetBookmarksFailure() {
// given

Expand All @@ -196,6 +197,48 @@ void testGetBookmarksFailure() {
assertThrows(NotFoundException.class, () -> bookmarkService.getBookmarks(mockMember, 0));
}

@Test
@DisplayName("북마크 가게 아이디 조회 성공 테스트")
void testGetBookmarkStoresIdsSuccess() {
// given
List<BookmarkStoreIdsResponseDto> bookmarks = List.of(
new BookmarkStoreIdsResponseDto(
1L,
1L
),
new BookmarkStoreIdsResponseDto(
1L,
2L
)
);


// when
when(memberRepository.findById(any())).thenReturn(Optional.of(member));
when(bookmarkRepository.findBookmarkStoreIdsByMemberId(any())).thenReturn(bookmarks);

// then
List<BookmarkStoreIdsResponseDto> response = bookmarkService.getBookmarkStoreIds(mockMember);
assertThat(response.get(0).bookmarkId()).isEqualTo(bookmarks.get(0).bookmarkId());
assertThat(response.get(1).bookmarkId()).isEqualTo(bookmarks.get(1).bookmarkId());
assertThat(response.get(0).storeId()).isEqualTo(bookmarks.get(0).storeId());
assertThat(response.get(1).storeId()).isEqualTo(bookmarks.get(1).storeId());

}

@Test
@DisplayName("북마크 가게 아이디 조회 시 회원 정보 없음으로 인한 실패 테스트")
void testGetBookmarkStoresIdsFailure() {
// given

// when
when(memberRepository.findById(any()))
.thenThrow(new NotFoundException(ResponseCode.MEMBER_NOT_FOUND_ID));

// then
assertThrows(NotFoundException.class, () -> bookmarkService.getBookmarkStoreIds(mockMember));
}

@Test
@DisplayName("북마크 삭제 성공 테스트")
void testDeleteBookmarkSuccess() {
Expand Down

0 comments on commit 75fd988

Please sign in to comment.