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
Expand Up @@ -3,14 +3,15 @@
import com.jiwon.mylog.domain.user.entity.User;
import jakarta.persistence.DiscriminatorValue;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToOne;

@Entity
@DiscriminatorValue("PROFILE")
public class ProfileImage extends Image {

@OneToOne
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;

Expand Down
12 changes: 12 additions & 0 deletions src/main/java/com/jiwon/mylog/domain/like/Like.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,17 @@
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;

@Getter
@EntityListeners(AuditingEntityListener.class)
@NoArgsConstructor
@Entity
@Table(
name = "likes",
Expand All @@ -44,4 +49,11 @@ public class Like {
@CreatedDate
@Column(nullable = false, updatable = false)
private LocalDateTime createdAt;

public static Like toLike(User user, Post post) {
Like like = new Like();
like.user = user;
like.post = post;
return like;
}
}
7 changes: 4 additions & 3 deletions src/main/java/com/jiwon/mylog/domain/like/LikeController.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.jiwon.mylog.domain.like;

import com.jiwon.mylog.global.common.entity.PageResponse;
import com.jiwon.mylog.global.common.entity.SliceResponse;
import com.jiwon.mylog.global.security.auth.annotation.LoginUser;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -47,10 +48,10 @@ public ResponseEntity<Boolean> getLikeStatus(@LoginUser Long userId, @PathVariab
}

@GetMapping("/users/{userId}/likes")
public ResponseEntity<?> getUserLikes(
public ResponseEntity<PageResponse> getUserLikes(
@PathVariable Long userId,
@PageableDefault(sort="createdAt", direction = Sort.Direction.DESC) Pageable pageable) {
SliceResponse response = likeService.getUserLikes(userId, pageable);
@PageableDefault(size = 10, sort="createdAt", direction = Sort.Direction.DESC) Pageable pageable) {
PageResponse response = likeService.getUserLikes(userId, pageable);
return ResponseEntity.ok(response);
}
}
14 changes: 12 additions & 2 deletions src/main/java/com/jiwon/mylog/domain/like/LikeRepository.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package com.jiwon.mylog.domain.like;

import com.jiwon.mylog.domain.post.entity.Post;
import org.springframework.data.domain.Page;
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.Modifying;
import org.springframework.data.jpa.repository.Query;
Expand All @@ -20,7 +21,16 @@ public interface LikeRepository extends JpaRepository<Like, Long> {
@Query(value = "delete from likes where user_id = :userId and post_id = :postId", nativeQuery = true)
void deleteLike(@Param("userId") Long userId, @Param("postId") Long postId);

Slice<Like> findAllByUserId(Long userId, Pageable pageable);
@Query("select p from Like l " +
"join l.post p " +
"left join fetch p.user u " +
"left join fetch u.profileImage " +
"left join fetch p.category " +
"left join fetch p.postTags pt " +
"left join fetch pt.tag " +
"where l.user.id = :userId and p.deletedAt is null " +
"order by l.createdAt desc")
Page<Post> findLikedPostByUserId(@Param("userId") Long userId, Pageable pageable);

@Query(value = "select count(*) from likes where post_id = :postId", nativeQuery = true)
long countByPostId(@Param("postId") Long postId);
Expand Down
29 changes: 19 additions & 10 deletions src/main/java/com/jiwon/mylog/domain/like/LikeService.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
package com.jiwon.mylog.domain.like;

import com.jiwon.mylog.domain.event.dto.LikeCreatedEvent;
import com.jiwon.mylog.domain.post.dto.response.PostSummaryResponse;
import com.jiwon.mylog.domain.post.entity.Post;
import com.jiwon.mylog.domain.post.repository.PostRepository;
import com.jiwon.mylog.domain.user.entity.User;
import com.jiwon.mylog.domain.user.repository.UserRepository;
import com.jiwon.mylog.global.common.entity.SliceResponse;
import com.jiwon.mylog.global.common.entity.PageResponse;
import com.jiwon.mylog.global.common.error.ErrorCode;
import com.jiwon.mylog.global.common.error.exception.NotFoundException;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@RequiredArgsConstructor
@Service
public class LikeService {
Expand All @@ -35,7 +39,8 @@ public void createLike(Long userId, Long postId) {
.orElseThrow(() -> new NotFoundException(ErrorCode.NOT_FOUND_POST));
Long receiverId = post.getUser().getId();

likeRepository.saveLike(userId, postId);
Like like = Like.toLike(user, post);
likeRepository.save(like);

if (!receiverId.equals(userId)) {
eventPublisher.publishEvent(
Expand Down Expand Up @@ -71,15 +76,19 @@ public boolean getLikeStatus(Long userId, Long postId) {
}

@Transactional(readOnly = true)
public SliceResponse getUserLikes(Long userId, Pageable pageable) {
public PageResponse getUserLikes(Long userId, Pageable pageable) {
validateUserExists(userId);
Slice<Like> likeSlice = likeRepository.findAllByUserId(userId, pageable);
return SliceResponse.from(
likeSlice.getContent(),
likeSlice.getNumber(),
likeSlice.getSize(),
likeSlice.isFirst(),
likeSlice.isLast()
Page<Post> postPage = likeRepository.findLikedPostByUserId(userId, pageable);
List<PostSummaryResponse> posts = postPage.getContent().stream()
.map(PostSummaryResponse::fromPost)
.toList();

return PageResponse.from(
posts,
postPage.getNumber(),
postPage.getSize(),
postPage.getTotalPages(),
postPage.getTotalElements()
);
}

Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/jiwon/mylog/domain/point/entity/Point.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
Expand All @@ -27,7 +28,7 @@ public class Point {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@OneToOne
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ public ResponseEntity<PageResponse> getUserPosts(

@GetMapping("/users/{userId}/categories/{categoryId}/posts")
@Operation(
summary = "특정 유저의 카테고리별 게시글 조회 (태그 필터링 포함)",
summary = "특정 유저의 카테고리별 게시글 조회 (태그 필터링 및 키워드 검색 포함)",
responses = {
@ApiResponse(responseCode = "200", description = "조회 성공"),
@ApiResponse(responseCode = "404", description = "존재하지 않는 사용자 혹은 카테고리")
Expand All @@ -149,9 +149,15 @@ public ResponseEntity<PageResponse> getPostsByCategoryAndTags(
@PathVariable("userId") Long userId,
@PathVariable("categoryId") Long categoryId,
@RequestParam(value = "tags", required = false) List<Long> tags,
@RequestParam(value = "keyword", required = false) String keyword,
@PageableDefault(size = 10, page = 0,
sort = "createdAt", direction = Direction.DESC) Pageable pageable) {
PageResponse response = postService.getPostsByCategoryAndTags(userId, categoryId, tags, pageable);
return new ResponseEntity<>(response, HttpStatus.OK);
if (keyword == null || keyword.isEmpty()) {
return ResponseEntity.ok(postService.getPostsByCategoryAndTags(
userId, categoryId, tags, "", pageable));
} else {
return ResponseEntity.ok(postService.searchPosts(
userId, categoryId, tags, keyword, pageable));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.fasterxml.jackson.annotation.JsonFormat;
import com.jiwon.mylog.domain.post.entity.Post;
import com.jiwon.mylog.domain.user.dto.response.UserResponse;
import com.jiwon.mylog.domain.user.dto.response.UserSummaryResponse;
import com.jiwon.mylog.global.common.enums.Visibility;
import com.jiwon.mylog.domain.category.dto.response.CategoryResponse;
import com.jiwon.mylog.domain.post.entity.PostStatus;
Expand All @@ -23,6 +25,7 @@ public class PostSummaryResponse {
private final Visibility visibility;
private final CategoryResponse category;
private final List<TagResponse> tags;
private final UserSummaryResponse user;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private final LocalDateTime createdAt;

Expand All @@ -37,6 +40,7 @@ public static PostSummaryResponse fromPost(Post post) {
.tags(post.getPostTags().stream()
.map(postTag -> TagResponse.fromTag(postTag.getTag()))
.toList())
.user(UserSummaryResponse.fromUser(post.getUser()))
.createdAt(post.getCreatedAt())
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
import java.util.Optional;

public interface PostRepositoryCustom {
Page<Post> findByCategoryAndTags(Long userId, Long categoryId, List<Long> tagIds, Pageable pageable);
Page<Post> findByTags(Long userId, List<Long> tagIds, Pageable pageable);
Page<Post> findByCategoryAndTags(Long userId, Long categoryId, List<Long> tagIds, String keyword, Pageable pageable);
Page<Post> findByTags(Long userId, List<Long> tagIds, String keyword, Pageable pageable);
Optional<PostDetailResponse> findPostDetail(Long postId);

List<UserActivityResponse> findUserActivities(Long userId, LocalDate start, LocalDate end);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.jiwon.mylog.domain.comment.dto.response.CommentResponse;
import com.jiwon.mylog.domain.comment.entity.QComment;
import com.jiwon.mylog.domain.image.entity.QProfileImage;
import com.jiwon.mylog.domain.point.entity.QPoint;
import com.jiwon.mylog.domain.post.dto.response.PostDetailResponse;
import com.jiwon.mylog.domain.post.entity.Post;
import com.jiwon.mylog.domain.post.entity.QPost;
Expand Down Expand Up @@ -51,14 +52,14 @@ public class PostRepositoryImpl implements PostRepositoryCustom{
private static final QComment COMMENT = QComment.comment;

@Override
public Page<Post> findByCategoryAndTags(Long userId, Long categoryId, List<Long> tagIds, Pageable pageable) {
BooleanBuilder builder = buildConditions(userId, categoryId,tagIds);
public Page<Post> findByCategoryAndTags(Long userId, Long categoryId, List<Long> tagIds, String keyword, Pageable pageable) {
BooleanBuilder builder = buildConditions(userId, categoryId, tagIds, keyword);
return createResult(pageable, builder);
}

@Override
public Page<Post> findByTags(Long userId, List<Long> tagIds, Pageable pageable) {
BooleanBuilder builder = buildConditions(userId, null, tagIds);
public Page<Post> findByTags(Long userId, List<Long> tagIds, String keyword, Pageable pageable) {
BooleanBuilder builder = buildConditions(userId, null, tagIds, keyword);
return createResult(pageable, builder);
}

Expand Down Expand Up @@ -183,6 +184,8 @@ private PageImpl<Post> createResult(Pageable pageable, BooleanBuilder builder) {
private List<Post> createPostsQuery(BooleanBuilder builder, Pageable pageable) {
return jpaQueryFactory
.selectFrom(POST)
.leftJoin(POST.user, USER).fetchJoin()
.leftJoin(POST.user.profileImage, PROFILE_IMAGE).fetchJoin()
.leftJoin(POST.category, CATEGORY).fetchJoin()
.leftJoin(POST.postTags, POST_TAG).fetchJoin()
.leftJoin(POST_TAG.tag, TAG).fetchJoin()
Expand All @@ -201,7 +204,7 @@ private Long createCountQuery(BooleanBuilder builder) {
.fetchOne();
}

private BooleanBuilder buildConditions(Long userId, Long categoryId, List<Long> tagIds) {
private BooleanBuilder buildConditions(Long userId, Long categoryId, List<Long> tagIds, String keyword) {
BooleanBuilder builder = new BooleanBuilder()
.and(POST.user.id.eq(userId))
.and(POST.deletedAt.isNull());
Expand All @@ -221,6 +224,10 @@ private BooleanBuilder buildConditions(Long userId, Long categoryId, List<Long>
builder.and(createTagExistsCondition(tagIds));
}

if (keyword != null && !keyword.isEmpty()) {
builder.and(POST.title.contains(keyword));
}

return builder;
}

Expand Down
35 changes: 32 additions & 3 deletions src/main/java/com/jiwon/mylog/domain/post/service/PostService.java
Original file line number Diff line number Diff line change
Expand Up @@ -216,14 +216,43 @@ public PageResponse getUserPosts(Long userId, Pageable pageable) {

@Cacheable(value = "post::filter", keyGenerator = "postCacheKeyGenerator")
@Transactional(readOnly = true)
public PageResponse getPostsByCategoryAndTags(Long userId, Long categoryId, List<Long> tagIds, Pageable pageable) {
public PageResponse getPostsByCategoryAndTags(
Long userId,
Long categoryId, List<Long> tagIds, String keyword,
Pageable pageable) {

Page<Post> postPage;

if (categoryId == null || categoryId.equals(0L)) {
postPage = postRepository.findByTags(userId, tagIds, pageable);
postPage = postRepository.findByTags(userId, tagIds, keyword, pageable);
} else {
postPage = postRepository.findByCategoryAndTags(userId, categoryId, tagIds, pageable);
postPage = postRepository.findByCategoryAndTags(userId, categoryId, tagIds, keyword, pageable);
}

List<PostSummaryResponse> posts = postPage.stream()
.map(PostSummaryResponse::fromPost)
.toList();

return PageResponse.from(
posts,
postPage.getNumber(),
postPage.getSize(),
postPage.getTotalPages(),
(int) postPage.getTotalElements());
}

@Transactional(readOnly = true)
public PageResponse searchPosts(
Long userId,
Long categoryId, List<Long> tagIds, String keyword,
Pageable pageable) {

Page<Post> postPage;

if (categoryId == null || categoryId.equals(0L)) {
postPage = postRepository.findByTags(userId, tagIds, keyword, pageable);
} else {
postPage = postRepository.findByCategoryAndTags(userId, categoryId, tagIds, keyword, pageable);
}

List<PostSummaryResponse> posts = postPage.stream()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.jiwon.mylog.domain.user.dto.response;

import com.jiwon.mylog.domain.user.entity.User;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

@AllArgsConstructor
@Builder
@Getter
public class UserSummaryResponse {
private final String username;
private final String imageKey;

public static UserSummaryResponse fromUser(User user) {
return UserSummaryResponse.builder()
.username(user.getUsername())
.imageKey(user.getProfileImage() == null ? "" : user.getProfileImage().getFileKey())
.build();
}
}
10 changes: 3 additions & 7 deletions src/main/java/com/jiwon/mylog/domain/user/entity/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
Expand Down Expand Up @@ -70,8 +71,8 @@ public class User extends BaseEntity {
@Column(nullable = false)
private Role role = Role.ROLE_USER;

@OneToOne(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private Point point;
// @OneToOne(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
// private Point point;

@Builder.Default
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
Expand Down Expand Up @@ -101,11 +102,6 @@ public class User extends BaseEntity {
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private List<UserItem> items = new ArrayList<>();

public void initUserPoint(Point point) {
this.point = point;
point.setUser(this);
}

public void updateProfile(String username, String bio) {
this.username = username;
this.bio = bio;
Expand Down
Loading