Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.example.log4u.domain.diary.controller;

import java.util.List;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
Expand All @@ -18,6 +20,7 @@
import com.example.log4u.domain.diary.SortType;
import com.example.log4u.domain.diary.dto.DiaryRequestDto;
import com.example.log4u.domain.diary.dto.DiaryResponseDto;
import com.example.log4u.domain.diary.dto.PopularDiaryDto;
import com.example.log4u.domain.diary.facade.DiaryFacade;

import jakarta.validation.Valid;
Expand Down Expand Up @@ -106,4 +109,10 @@ public ResponseEntity<Void> deleteDiary(
diaryFacade.deleteDiary(customOAuth2User.getUserId(), diaryId);
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
}

@GetMapping("/popular")
public ResponseEntity<List<PopularDiaryDto>> getPopularDiaries() {
List<PopularDiaryDto> popularDiaries = diaryFacade.getPopularDiaries(10);
return ResponseEntity.ok(popularDiaries);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,31 @@ public static DiaryResponseDto of(
.build();
}

// DiaryWithAuthorDto 전용 메서드
public static DiaryResponseDto of(
DiaryWithAuthorDto dto,
List<Media> media,
List<String> hashtagList
) {
return DiaryResponseDto.builder()
.diaryId(dto.diary().getDiaryId())
.authorId(dto.diary().getUserId())
.authorNickname(dto.authorNickname())
.authorProfileImage(dto.authorProfileImage())
.location(LocationDto.of(dto.diary().getLocation()))
.title(dto.diary().getTitle())
.content(dto.diary().getContent())
.weatherInfo(dto.diary().getWeatherInfo().name())
.visibility(dto.diary().getVisibility().name())
.createdAt(dto.diary().getCreatedAt())
.updatedAt(dto.diary().getUpdatedAt())
.thumbnailUrl(dto.diary().getThumbnailUrl())
.likeCount(dto.diary().getLikeCount())
.mediaList(media.stream()
.map(MediaResponseDto::of).toList())
.hashtagList(hashtagList)
.isLiked(false)
.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.example.log4u.domain.diary.dto;

import com.example.log4u.domain.diary.entity.Diary;

public record DiaryWithAuthorDto(
Diary diary,
String authorNickname,
String authorProfileImage
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.example.log4u.domain.diary.dto;

import com.example.log4u.domain.diary.entity.Diary;

import lombok.Builder;

@Builder
public record PopularDiaryDto(
Long diaryId,
String title
) {
public static PopularDiaryDto of(Diary diary) {
return PopularDiaryDto.builder()
.diaryId(diary.getDiaryId())
.title(diary.getTitle())
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.example.log4u.domain.diary.SortType;
import com.example.log4u.domain.diary.dto.DiaryRequestDto;
import com.example.log4u.domain.diary.dto.DiaryResponseDto;
import com.example.log4u.domain.diary.dto.PopularDiaryDto;
import com.example.log4u.domain.diary.entity.Diary;
import com.example.log4u.domain.diary.service.DiaryService;
import com.example.log4u.domain.hashtag.service.HashtagService;
Expand Down Expand Up @@ -139,4 +140,16 @@ public PageResponse<DiaryResponseDto> searchDiariesByCursor(
Long nextCursor = !dtoSlice.isEmpty() ? dtoSlice.getContent().getLast().diaryId() : null;
return PageResponse.of(dtoSlice, nextCursor);
}

@Transactional(readOnly = true)
public List<PopularDiaryDto> getPopularDiaries(int limit) {
List<Diary> popularDiaries = diaryService.getTop10Diaries();

if (popularDiaries.isEmpty()) {
return List.of();
}
return popularDiaries.stream()
.map(PopularDiaryDto::of)
.toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,25 @@

import java.util.List;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;

import com.example.log4u.domain.diary.SortType;
import com.example.log4u.domain.diary.VisibilityType;
import com.example.log4u.domain.diary.dto.DiaryWithAuthorDto;
import com.example.log4u.domain.diary.entity.Diary;
import com.example.log4u.domain.map.dto.response.DiaryMarkerResponseDto;

public interface CustomDiaryRepository {
Page<Diary> searchDiaries(
String keyword,
List<VisibilityType> visibilities,
SortType sort,
Pageable pageable
);

Slice<Diary> findByUserIdAndVisibilityInAndCursorId(
Slice<DiaryWithAuthorDto> findByUserIdAndVisibilityInAndCursorId(
Long userId,
List<VisibilityType> visibilities,
Long cursorId,
Pageable pageable
);

Slice<Diary> searchDiariesByCursor(
Slice<DiaryWithAuthorDto> searchDiariesByCursor(
String keyword,
List<VisibilityType> visibilities,
SortType sort,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

import java.util.List;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.stereotype.Repository;
Expand All @@ -12,18 +10,18 @@
import com.example.log4u.common.util.PageableUtil;
import com.example.log4u.domain.diary.SortType;
import com.example.log4u.domain.diary.VisibilityType;
import com.example.log4u.domain.diary.dto.DiaryWithAuthorDto;
import com.example.log4u.domain.diary.entity.Diary;
import com.example.log4u.domain.diary.entity.QDiary;
import com.example.log4u.domain.hashtag.entity.QDiaryHashtag;
import com.example.log4u.domain.hashtag.entity.QHashtag;
import com.example.log4u.domain.like.entity.QLike;
import com.example.log4u.domain.map.dto.response.DiaryMarkerResponseDto;
import com.example.log4u.domain.media.entity.QMedia;
import com.example.log4u.domain.user.entity.QUser;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.JPAExpressions;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;

import lombok.RequiredArgsConstructor;
Expand All @@ -38,42 +36,10 @@ public class CustomDiaryRepositoryImpl implements CustomDiaryRepository {
private final QLike like = QLike.like;
private final QDiaryHashtag diaryHashtag = QDiaryHashtag.diaryHashtag;
private final QHashtag hashtag = QHashtag.hashtag;
private final QMedia media = QMedia.media;
private final QUser user = QUser.user;

@Override
public Page<Diary> searchDiaries(
String keyword,
List<VisibilityType> visibilities,
SortType sort,
Pageable pageable
) {
// 조건 생성
BooleanExpression condition = createSearchCondition(keyword, visibilities, null);

// 쿼리 실행
JPAQuery<Diary> query = queryFactory
.selectFrom(diary)
.where(condition);

// 전체 카운트 조회
Long total = queryFactory
.select(diary.count())
.from(diary)
.where(condition)
.fetchOne();

// 데이터 조회
List<Diary> content = query
.orderBy(createOrderSpecifier(sort))
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();

return new PageImpl<>(content, pageable, total != null ? total : 0);
}

@Override
public Slice<Diary> findByUserIdAndVisibilityInAndCursorId(
public Slice<DiaryWithAuthorDto> findByUserIdAndVisibilityInAndCursorId(
Long userId,
List<VisibilityType> visibilities,
Long cursorId,
Expand Down Expand Up @@ -104,9 +70,15 @@ public Slice<Diary> findByUserIdAndVisibilityInAndCursorId(
}
}

// limit + 1로 다음 페이지 존재 여부 확인
List<Diary> content = queryFactory
.selectFrom(diary)
// 다이어리와 작성자 정보를 함께 조회
List<DiaryWithAuthorDto> content = queryFactory
.select(Projections.constructor(DiaryWithAuthorDto.class,
diary,
user.nickname,
user.profileImage
))
.from(diary)
.join(user).on(diary.userId.eq(user.userId))
.where(condition)
.orderBy(diary.createdAt.desc(), diary.diaryId.desc())
.limit(pageable.getPageSize() + 1)
Expand All @@ -117,7 +89,7 @@ public Slice<Diary> findByUserIdAndVisibilityInAndCursorId(
}

@Override
public Slice<Diary> searchDiariesByCursor(
public Slice<DiaryWithAuthorDto> searchDiariesByCursor(
String keyword,
List<VisibilityType> visibilities,
SortType sort,
Expand Down Expand Up @@ -162,9 +134,15 @@ public Slice<Diary> searchDiariesByCursor(
}
}

// limit + 1로 다음 페이지 존재 여부 확인
List<Diary> content = queryFactory
.selectFrom(diary)
// 다이어리와 작성자 정보를 함께 조회
List<DiaryWithAuthorDto> content = queryFactory
.select(Projections.constructor(DiaryWithAuthorDto.class,
diary,
user.nickname,
user.profileImage
))
.from(diary)
.join(user).on(diary.userId.eq(user.userId))
.where(condition)
.orderBy(createOrderSpecifier(sort))
.limit(pageable.getPageSize() + 1)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package com.example.log4u.domain.diary.repository;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;

import com.example.log4u.domain.diary.VisibilityType;
import com.example.log4u.domain.diary.entity.Diary;

public interface DiaryRepository extends JpaRepository<Diary, Long>, CustomDiaryRepository {
List<Diary> findTop10ByVisibilityOrderByLikeCountDesc(VisibilityType visibility);
}
Loading