diff --git a/src/main/java/EatPic/spring/domain/bookmark/repository/BookmarkRepository.java b/src/main/java/EatPic/spring/domain/bookmark/repository/BookmarkRepository.java index d2a67b1..bf4f0b1 100644 --- a/src/main/java/EatPic/spring/domain/bookmark/repository/BookmarkRepository.java +++ b/src/main/java/EatPic/spring/domain/bookmark/repository/BookmarkRepository.java @@ -3,8 +3,17 @@ import EatPic.spring.domain.bookmark.entity.Bookmark; import EatPic.spring.domain.bookmark.entity.BookmarkId; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; +import java.util.Set; public interface BookmarkRepository extends JpaRepository { boolean existsByCardIdAndUserId(Long cardId, Long userId); + + @Query("SELECT b.card.id FROM Bookmark b WHERE b.user.id = :userId AND b.card.id IN :cardIds") + Set findCardIdsByUserIdAndCardIdIn(@Param("userId") Long userId, @Param("cardIds") List cardIds); + } diff --git a/src/main/java/EatPic/spring/domain/card/controller/CardController.java b/src/main/java/EatPic/spring/domain/card/controller/CardController.java index 9df0228..39956e2 100644 --- a/src/main/java/EatPic/spring/domain/card/controller/CardController.java +++ b/src/main/java/EatPic/spring/domain/card/controller/CardController.java @@ -132,11 +132,10 @@ public ResponseEntity> updateCard( @GetMapping("/feeds") public ApiResponse getFeeds( HttpServletRequest request, + @RequestParam(required = false) Long userId, @RequestParam(required = false) Long cursor, @RequestParam(defaultValue = "15") int size) { - - User user = userService.getLoginUser(request); - return ApiResponse.onSuccess(cardService.getCardFeedByCursor(request,user.getId(),size,cursor)); + return ApiResponse.onSuccess(cardService.getCardFeedByCursor(request,userId,size,cursor)); } diff --git a/src/main/java/EatPic/spring/domain/card/repository/CardHashtagRepository.java b/src/main/java/EatPic/spring/domain/card/repository/CardHashtagRepository.java index d9a6439..90df44c 100644 --- a/src/main/java/EatPic/spring/domain/card/repository/CardHashtagRepository.java +++ b/src/main/java/EatPic/spring/domain/card/repository/CardHashtagRepository.java @@ -15,4 +15,6 @@ public interface CardHashtagRepository extends JpaRepository List findByHashtag(Hashtag hashtag); // Hashtag 객체 List findByHashtagId(Long hashtagId); // Hashtag의 PK값 + + List findByCardIdIn(List cardIds); } diff --git a/src/main/java/EatPic/spring/domain/card/repository/CardRepository.java b/src/main/java/EatPic/spring/domain/card/repository/CardRepository.java index 39a291f..cce1f04 100644 --- a/src/main/java/EatPic/spring/domain/card/repository/CardRepository.java +++ b/src/main/java/EatPic/spring/domain/card/repository/CardRepository.java @@ -33,13 +33,15 @@ public interface CardRepository extends JpaRepository { List findAllByUserAndCreatedAtBetween(User user, LocalDateTime start, LocalDateTime end); - @Query(""" -SELECT c +@Query(""" +SELECT DISTINCT c FROM Card c +JOIN FETCH c.user u +LEFT JOIN FETCH c.cardHashtags ch WHERE c.isDeleted = false AND c.isShared = true - AND c.user.id <> :loginUserId - AND c.user.id NOT IN ( + AND u.id <> :loginUserId + AND u.id NOT IN ( SELECT ub.blockedUser.id FROM UserBlock ub WHERE ub.user.id = :loginUserId diff --git a/src/main/java/EatPic/spring/domain/card/service/CardServiceImpl.java b/src/main/java/EatPic/spring/domain/card/service/CardServiceImpl.java index 1be96ab..28850ca 100644 --- a/src/main/java/EatPic/spring/domain/card/service/CardServiceImpl.java +++ b/src/main/java/EatPic/spring/domain/card/service/CardServiceImpl.java @@ -32,10 +32,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.UUID; +import java.util.*; import java.util.stream.Collectors; import jakarta.servlet.http.HttpServletRequest; @@ -309,9 +306,9 @@ public CardDetailResponse updateCard(Long cardId, User user, CardUpdateRequest r @Transactional(readOnly = true) public CardResponse.PagedCardFeedResponseDto getCardFeedByCursor(HttpServletRequest request, Long userId, int size, Long cursor) { User me = userService.getLoginUser(request); - Slice cardSlice; Pageable pageable = PageRequest.of(0, size); + if(userId == null) { // 전체 선택 cardSlice = cardRepository.findFeedExcludeBlocked(me.getId(),cursor,pageable); }else if(userId.equals(me.getId())){ // 내 피드 조회 @@ -335,14 +332,46 @@ public CardResponse.PagedCardFeedResponseDto getCardFeedByCursor(HttpServletRequ throw new ExceptionHandler(NO_RECENT_CARDS); } } + if(cardSlice.isEmpty()){ throw new ExceptionHandler(CARD_NOT_FOUND); } + + List cardIds = cardSlice.stream().map(Card::getId).toList(); + + Map> hashtagsMap = cardHashtagRepository.findByCardIdIn(cardIds).stream() + .collect(Collectors.groupingBy(ch -> ch.getCard().getId())); + + Map reactionMap = reactionRepository.findByCardIdInAndUserId(cardIds, me.getId()).stream() + .collect(Collectors.toMap(r -> r.getCard().getId(), r -> r)); + + Map reactionCountMap = reactionRepository.countByCardIdIn(cardIds).stream() + .collect(Collectors.toMap( + r -> (Long) r[0], // cardId + r -> ((Long) r[1]).intValue() // count + )); + + Map commentCountMap = commentRepository.countByCardIdIn(cardIds).stream() + .collect(Collectors.toMap( + r -> (Long) r[0], + r -> ((Long) r[1]).intValue() + )); + + Set bookmarkedCardIds = bookmarkRepository.findCardIdsByUserIdAndCardIdIn(me.getId(), cardIds); + List feedList = cardSlice.stream() - .map(card -> getCardFeed(card.getId(),userId)) + .map(card -> CardConverter.toFeedResponse( + card, + hashtagsMap.getOrDefault(card.getId(), Collections.emptyList()), + card.getUser(), + reactionMap.get(card.getId()),// 로그인 유저가 작성한 반응 + reactionCountMap.getOrDefault(card.getId(), 0), + commentCountMap.getOrDefault(card.getId(), 0), + bookmarkedCardIds.contains(card.getId()) + )) .toList(); - return CardConverter.toPagedCardFeedResponseDTto(userId,cardSlice,feedList); + return CardConverter.toPagedCardFeedResponseDTto(userId, cardSlice, feedList); } @Override diff --git a/src/main/java/EatPic/spring/domain/comment/repository/CommentRepository.java b/src/main/java/EatPic/spring/domain/comment/repository/CommentRepository.java index 2fcafc2..8fa9a94 100644 --- a/src/main/java/EatPic/spring/domain/comment/repository/CommentRepository.java +++ b/src/main/java/EatPic/spring/domain/comment/repository/CommentRepository.java @@ -5,6 +5,8 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import java.util.List; @@ -22,4 +24,7 @@ Slice findAllByCardAndParentCommentIsNullAndIdGreaterThanOrderByIdAsc( int countByCardId(Long cardId); + @Query("SELECT c.card.id, COUNT(c) FROM Comment c WHERE c.card.id IN :cardIds GROUP BY c.card.id") + List countByCardIdIn(@Param("cardIds") List cardIds); + } diff --git a/src/main/java/EatPic/spring/domain/reaction/repository/ReactionRepository.java b/src/main/java/EatPic/spring/domain/reaction/repository/ReactionRepository.java index a6b5fcc..3aea669 100644 --- a/src/main/java/EatPic/spring/domain/reaction/repository/ReactionRepository.java +++ b/src/main/java/EatPic/spring/domain/reaction/repository/ReactionRepository.java @@ -5,6 +5,8 @@ import EatPic.spring.domain.reaction.entity.ReactionId; import EatPic.spring.domain.reaction.entity.ReactionType; import EatPic.spring.domain.user.entity.User; + +import java.util.List; import java.util.Optional; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -29,5 +31,10 @@ Page findUsersByCardAndReactionType(@Param("cardId") Long cardId, long countByCardAndReactionType(Card card, ReactionType reactionType); + // 카드별 작성 반응 + List findByCardIdInAndUserId(List cardIds, Long userId); + + @Query("SELECT r.card.id, COUNT(r) FROM Reaction r WHERE r.card.id IN :cardIds GROUP BY r.card.id") + List countByCardIdIn(@Param("cardIds") List cardIds); }