티스토리 뷰
게시글 북마크 기능은 다 만들었고, 이제 유저(멤버)의 북마크 페이지나 마이 페이지에서 북마크한 목록을 조회하는 기능을 구현할 것이다.
Dto
MyBookamrkDto
package com.example.MyFreshmanCommunity.dto;
import com.example.MyFreshmanCommunity.entity.Article;
import com.example.MyFreshmanCommunity.entity.Major;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class MyBookmarkDto {
private Long id;
private String title;
private String content;
private LocalDateTime createDate;
private LoginResponseDto member;
private Major major;
public static MyBookmarkDto createMyBookmarkDto(Article article){
return new MyBookmarkDto(
article.getId(),
article.getTitle(),
article.getContent(),
article.getCreateDate(),
LoginResponseDto.createLoginDto(article.getMember()),
article.getMajor()
);
}
}
사실 ArticleResponseDto랑 다른 게 없지만 구분하는 게 더 이해하기 편할 것 같아 구분하여 클래스를 만들어주었다.
유저가 북마크한 게시글의 목록들이 createBookmarkDto메서드를 통해 MyBookmarkDto에 담겨 반환될 것이다.
BookmarkRepository
List<Bookmark> findAllByMember(Member member);
Service
MemberService
❗️❗️❗️틀린코드❗️❗️❗️
public List<MyBookmarkDto> myBookmark(HttpSession session) {
Member member = (Member) session.getAttribute("member");
List<Article> bookmarks = articleRepository.findAllByIdIn(bookmarkRepository.findAllArticleIdByMember(member));
List<MyBookmarkDto> dtos = new ArrayList<MyBookmarkDto>();
for(Article a: bookmarks) {
MyBookmarkDto dto = MyBookmarkDto.createBookmarkDto(a);
dtos.add(dto);
}
return dtos;
}
처음에는 되게 복잡하게 생각했다.
findAllArticleIdByMember 메서드를 호출하여 회원의 북마크된 게시물의 ID 목록을 가져온 다음, 이 ID 목록을 사용하여 findAllByIdIn 메서드를 호출하여 해당 ID를 가진 게시물을 가져왔다. 그런 다음 가져온 각 게시물을 MyBookmarkDto로 변환하여 리스트에 추가해주었다. 그러나 이렇게 하면 두 번의 데이터베이스 쿼리를 실행하므로 데이터베이스 부하가 발생할 뿐만 아니라, postman으로 돌려보았을 때 "Specified result type [java.lang.Long] did not match Query selection type [com.example.MyFreshmanCommunity.entity.Bookmark] - multiple selections: use Tuple or array" 라는 오류 메시지가 나타났다. 찾아보니 이 오류는 여러 선택 항목이 있는 쿼리에서 단일 타입을 반환하려고 할 때 발생하는데, 따라서 여러 개의 엔티티나 다른 객체를 선택한 경우에는 해당 결과를 Tuple이나 배열로 반환해야 한다.
❗️❗️❗️두번째 틀린코드❗️❗️❗️
public List<MyBookmarkDto> myBookmark(HttpSession session) {
Member member = (Member) session.getAttribute("member");
// Member로부터 Article ID 목록 가져오기
List<Tuple> articleTuples = bookmarkRepository.findAllArticleIdByMember(member);
List<Long> articleIds = new ArrayList<>();
for (Tuple tuple : articleTuples) {
// Tuple에서 Article ID를 가져와서 List<Long>에 추가
Long articleId = (Long) tuple.get(0);
articleIds.add(articleId);
}
// Article ID 목록을 사용하여 Article 목록 조회
List<Article> bookmarks = articleRepository.findAllByIdIn(articleIds);
// Article 목록을 MyBookmarkDto로 변환
List<MyBookmarkDto> dtos = new ArrayList<>();
for (Article a: bookmarks) {
MyBookmarkDto dto = MyBookmarkDto.createBookmarkDto(a);
dtos.add(dto);
}
return dtos;
}
따라서 투플을 이용한 코드로 바꿔보았지만,,, 이번엔 Invoked method is not a property accessor라는 오류가 떴다. 이 오류는 스프링 데이터 프로젝션에서 사용되는 메서드가 올바른 방식으로 호출되지 않았을 때 발생한다.
이를통해 내가 생각했던 방식은 아예 잘못되었음을 깨닫고, 다시 처음부터 생각해보았다. ㅎㅎ
🌟🌟최종코드🌟🌟
public List<MyBookmarkDto> myBookmark(HttpSession session) {
Member member = (Member) session.getAttribute("member");
return bookmarkRepository.findAllByMember(member).stream()
.map(bookmark -> MyBookmarkDto.createMyBookmarkDto(bookmark.getArticle()))
.collect(Collectors.toList());
}
두 번의 데이터베이스 쿼리를 호출할 필요 없이, findAllByMember 메서드를 사용하여 회원의 북마크된 항목을 한 번에 가져오고, 그런 다음 각 북마크 항목을 MyBookmarkDto로 매핑하여 최종 결과를 얻으면 된다.
이 방법은 스트림 및 람다 표현식을 사용하여 코드를 간결하게 유지할 수 있을 뿐만 아니라, 하나의 쿼리만 사용하므로 데이터베이스 부하가 줄어들게 된다.
Controller
MemberApiController
//나의 북마크
@GetMapping("/user/bookmark")
public ResponseEntity<List<MyBookmarkDto>> myBookmark(HttpServletRequest request) {
HttpSession session = request.getSession();
List<MyBookmarkDto> bookmarks = memberService.myBookmark(session);
return ResponseEntity.status(HttpStatus.OK).body(bookmarks);
}
유저가 여러개의 게시글을 북마크할 수 있으므로 반환타입을 <List<MyBookmarkDto>>로 해주었다. 또한 유저마다의 북마크 목록을 가져오기 위해 현재 로그인되어있는 멤버의 세션을 가져와주었다.
postman을 통한 데이터 확인
'Spring' 카테고리의 다른 글
스프링 커뮤니티 만들기 #10 -회원탈퇴 시 오류해결 2 (NullpointerException) (0) | 2024.03.03 |
---|---|
스프링 커뮤니티 만들기 #9 - 회원탈퇴 시 오류해결 (외래키 제약조건) (1) | 2024.03.03 |
스프링 커뮤니티 만들기 #7 - 게시글 북마크 (0) | 2024.03.03 |
스프링 커뮤니티 만들기 #6 - 댓글 좋아요 (0) | 2024.03.03 |
스프링부트 커뮤니티 만들기 #5 - 댓글 CRUD (0) | 2024.03.03 |
- Total
- Today
- Yesterday
- 로깅
- 프론트엔드
- 준영속
- 인텔리제이
- 커뮤니티
- DP
- EnumType.ORDINAL
- 회원탈퇴
- 스프링 커뮤니티
- elasticsearch
- 로그아웃
- 자바
- 지연로딩
- 영속
- SQL 레벨업
- 스프링 북마크
- 백준 파이썬
- 웹MVC
- 비영속
- 스프링부트
- 웹 MVC
- 스프링
- 다이나믹 프로그래밍
- SQLD
- JPA
- 자바 스프링
- SQL
- 북마크
- 백준
- 파이썬
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |