From 79ed4f897be03c8167fa107681db90f4e8c350da Mon Sep 17 00:00:00 2001 From: JIN-076 <57834671+JIN-076@users.noreply.github.com> Date: Mon, 19 Feb 2024 11:28:35 +0900 Subject: [PATCH] =?UTF-8?q?[FEAT]=20ProfileCard=EC=99=80=20ProfileCardLike?= =?UTF-8?q?=20=EC=97=94=ED=8B=B0=ED=8B=B0=20=EA=B5=AC=ED=98=84=20(#81)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [FEAT] ProfileCard와 ProfileCardLike 엔티티 구현 * [FEAT] ProfileCard 동적 쿼리 조회 메서드 구현, 커서 기반 페이지네이션 적용 --- .../profile/domain/entity/ProfileCard.java | 49 +++++++++++++++ .../domain/entity/ProfileCardLike.java | 60 +++++++++++++++++++ .../ProfileCardJpaRepository.java | 10 ++++ .../ProfileCardRepositoryCustom.java | 13 ++++ .../ProfileCardRepositoryCustomImpl.java | 57 ++++++++++++++++++ 5 files changed, 189 insertions(+) create mode 100644 src/main/java/io/oeid/mogakgo/domain/profile/domain/entity/ProfileCard.java create mode 100644 src/main/java/io/oeid/mogakgo/domain/profile/domain/entity/ProfileCardLike.java create mode 100644 src/main/java/io/oeid/mogakgo/domain/profile/infrastructure/ProfileCardJpaRepository.java create mode 100644 src/main/java/io/oeid/mogakgo/domain/profile/infrastructure/ProfileCardRepositoryCustom.java create mode 100644 src/main/java/io/oeid/mogakgo/domain/profile/infrastructure/ProfileCardRepositoryCustomImpl.java diff --git a/src/main/java/io/oeid/mogakgo/domain/profile/domain/entity/ProfileCard.java b/src/main/java/io/oeid/mogakgo/domain/profile/domain/entity/ProfileCard.java new file mode 100644 index 00000000..a987c3bd --- /dev/null +++ b/src/main/java/io/oeid/mogakgo/domain/profile/domain/entity/ProfileCard.java @@ -0,0 +1,49 @@ +package io.oeid.mogakgo.domain.profile.domain.entity; + +import io.oeid.mogakgo.domain.user.domain.User; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Entity +@Table(name = "profile_card_tb") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class ProfileCard { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "profile_card_id") + private Long id; + + @OneToOne(cascade = CascadeType.ALL) + @JoinColumn(name = "user_id", updatable = false) + private User user; + + @Column(name = "total_like_amount", nullable = false) + private Long totalLikeAmount; + + @Builder + private ProfileCard(User user) { + this.user = user; + this.totalLikeAmount = 0L; + } + + public static ProfileCard from(User user) { + return ProfileCard.builder() + .user(user) + .build(); + } +} diff --git a/src/main/java/io/oeid/mogakgo/domain/profile/domain/entity/ProfileCardLike.java b/src/main/java/io/oeid/mogakgo/domain/profile/domain/entity/ProfileCardLike.java new file mode 100644 index 00000000..9587096f --- /dev/null +++ b/src/main/java/io/oeid/mogakgo/domain/profile/domain/entity/ProfileCardLike.java @@ -0,0 +1,60 @@ +package io.oeid.mogakgo.domain.profile.domain.entity; + +import io.oeid.mogakgo.domain.user.domain.User; +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; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import java.time.LocalDateTime; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +@Getter +@Entity +@Table(name = "profile_card_like_tb") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@EntityListeners(AuditingEntityListener.class) +public class ProfileCardLike { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "profile_card_like_id") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "sender_id", updatable = false) + private User sender; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "receiver_id", updatable = false) + private User receiver; + + @CreatedDate + @Column(name = "created_at") + private LocalDateTime createdAt; + + @Builder + private ProfileCardLike(User sender, User receiver) { + this.sender = sender; + this.receiver = receiver; + } + + public static ProfileCardLike of(User sender, User receiver) { + return ProfileCardLike.builder() + .sender(sender) + .receiver(receiver) + .build(); + } +} diff --git a/src/main/java/io/oeid/mogakgo/domain/profile/infrastructure/ProfileCardJpaRepository.java b/src/main/java/io/oeid/mogakgo/domain/profile/infrastructure/ProfileCardJpaRepository.java new file mode 100644 index 00000000..bb45a235 --- /dev/null +++ b/src/main/java/io/oeid/mogakgo/domain/profile/infrastructure/ProfileCardJpaRepository.java @@ -0,0 +1,10 @@ +package io.oeid.mogakgo.domain.profile.infrastructure; + +import io.oeid.mogakgo.domain.profile.domain.entity.ProfileCard; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ProfileCardJpaRepository extends JpaRepository, ProfileCardRepositoryCustom { + +} diff --git a/src/main/java/io/oeid/mogakgo/domain/profile/infrastructure/ProfileCardRepositoryCustom.java b/src/main/java/io/oeid/mogakgo/domain/profile/infrastructure/ProfileCardRepositoryCustom.java new file mode 100644 index 00000000..fdb6ba43 --- /dev/null +++ b/src/main/java/io/oeid/mogakgo/domain/profile/infrastructure/ProfileCardRepositoryCustom.java @@ -0,0 +1,13 @@ +package io.oeid.mogakgo.domain.profile.infrastructure; + +import io.oeid.mogakgo.domain.geo.domain.enums.Region; +import io.oeid.mogakgo.domain.profile.domain.entity.ProfileCard; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; + +public interface ProfileCardRepositoryCustom { + + Slice findByCondition( + Long cursorId, Long userId, Region region, Pageable pageable + ); +} diff --git a/src/main/java/io/oeid/mogakgo/domain/profile/infrastructure/ProfileCardRepositoryCustomImpl.java b/src/main/java/io/oeid/mogakgo/domain/profile/infrastructure/ProfileCardRepositoryCustomImpl.java new file mode 100644 index 00000000..31bad7b1 --- /dev/null +++ b/src/main/java/io/oeid/mogakgo/domain/profile/infrastructure/ProfileCardRepositoryCustomImpl.java @@ -0,0 +1,57 @@ +package io.oeid.mogakgo.domain.profile.infrastructure; + +import static io.oeid.mogakgo.domain.profile.domain.entity.QProfileCard.profileCard; + +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.jpa.impl.JPAQueryFactory; +import io.oeid.mogakgo.domain.geo.domain.enums.Region; +import io.oeid.mogakgo.domain.profile.domain.entity.ProfileCard; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.data.domain.SliceImpl; +import org.springframework.stereotype.Repository; + +@Repository +@RequiredArgsConstructor +public class ProfileCardRepositoryCustomImpl implements ProfileCardRepositoryCustom { + + private final JPAQueryFactory jpaQueryFactory; + + @Override + public Slice findByCondition( + Long cursorId, Long userId, Region region, Pageable pageable + ) { + List result = jpaQueryFactory.selectFrom(profileCard) + .where( + cursorIdEq(cursorId), + userIdEq(userId), + regionEq(region) + ) + .limit(pageable.getPageSize() + 1) + .fetch(); + boolean hasNext = checkLastPage(result, pageable); + return new SliceImpl<>(result, pageable, hasNext); + } + + private BooleanExpression regionEq(Region region) { + return region != null ? profileCard.user.region.eq(region) : null; + } + + private BooleanExpression userIdEq(Long userId) { + return userId != null ? profileCard.user.id.eq(userId) : null; + } + + private BooleanExpression cursorIdEq(Long cursorId) { + return cursorId != null ? profileCard.id.gt(cursorId) : null; + } + + private boolean checkLastPage(List profileCards, Pageable pageable) { + if (profileCards.size() > pageable.getPageSize()) { + profileCards.remove(pageable.getPageSize()); + return true; + } + return false; + } +}