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 @@ -6,14 +6,12 @@
import kr.spot.study.domain.associations.StudyCategory;
import kr.spot.study.domain.associations.StudyMember;
import kr.spot.study.domain.associations.StudyRegion;
import kr.spot.study.domain.associations.StudyStats;
import kr.spot.study.domain.associations.StudyStyle;
import kr.spot.study.domain.vo.Fee;
import kr.spot.study.infrastructure.jpa.StudyRepository;
import kr.spot.study.infrastructure.jpa.associations.StudyCategoryRepository;
import kr.spot.study.infrastructure.jpa.associations.StudyMemberRepository;
import kr.spot.study.infrastructure.jpa.associations.StudyRegionRepository;
import kr.spot.study.infrastructure.jpa.associations.StudyStatsRepository;
import kr.spot.study.infrastructure.jpa.associations.StudyStyleRepository;
import kr.spot.study.presentation.command.dto.request.CreateStudyRequest;
import lombok.RequiredArgsConstructor;
Expand All @@ -34,18 +32,15 @@ public class CreateStudyService {
private final StudyStyleRepository studyStyleRepository;
private final StudyRegionRepository studyRegionRepository;
private final StudyCategoryRepository studyCategoryRepository;
private final StudyStatsRepository studyStatsRepository;
private final StudyMemberRepository studyMemberRepository;

public long createStudy(CreateStudyRequest request, long leaderId, MultipartFile imageFile) {
long studyId = idGenerator.nextId();
Study study = Study.of(studyId, leaderId, request.name(), request.maxMembers(),
Fee.of(request.hasFee(), request.amount()), null, request.description(), request.isOnline());
StudyStats studyStats = StudyStats.of(studyId);
StudyMember studyMember = StudyMember.create(idGenerator.nextId(), studyId, leaderId);

studyRepository.save(study);
studyStatsRepository.save(studyStats);
studyMemberRepository.save(studyMember);

saveAllStudyCategories(request, studyId);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package kr.spot.study.application.command;

import kr.spot.IdGenerator;
import kr.spot.study.infrastructure.jpa.StudyRepository;
import kr.spot.study.infrastructure.jpa.associations.StudyLikeRepository;
import kr.spot.study.infrastructure.jpa.associations.StudyStatsRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -14,7 +14,7 @@ public class StudyLikeService {

private final IdGenerator idGenerator;
private final StudyLikeRepository studyLikeRepository;
private final StudyStatsRepository studyStatsRepository;
private final StudyRepository studyRepository;

public void likeStudy(long studyId, long memberId) {
int inserted = studyLikeRepository.saveStudyLike(idGenerator.nextId(), studyId, memberId);
Expand All @@ -23,14 +23,14 @@ public void likeStudy(long studyId, long memberId) {

private void increaseLikeCount(long studyId, int inserted) {
if (inserted == 1) {
studyStatsRepository.increaseLike(studyId);
studyRepository.increaseLike(studyId);
}
}

public void unlikeStudy(long studyId, long memberId) {
int deleted = studyLikeRepository.hardDelete(studyId, memberId);
if (deleted > 0) {
studyStatsRepository.decreaseLike(studyId);
studyRepository.decreaseLike(studyId);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,11 @@
import kr.spot.study.domain.Study;
import kr.spot.study.domain.associations.StudyCategory;
import kr.spot.study.domain.associations.StudyMember;
import kr.spot.study.domain.associations.StudyStats;
import kr.spot.study.domain.enums.Category;
import kr.spot.study.domain.enums.StudyMemberStatus;
import kr.spot.study.infrastructure.jpa.StudyRepository;
import kr.spot.study.infrastructure.jpa.associations.StudyCategoryRepository;
import kr.spot.study.infrastructure.jpa.associations.StudyMemberRepository;
import kr.spot.study.infrastructure.jpa.associations.StudyStatsRepository;
import kr.spot.study.presentation.query.dto.response.GetStudyInfoResponse;
import kr.spot.study.presentation.query.dto.response.GetStudyInfoResponse.Statistics;
import kr.spot.study.presentation.query.dto.response.GetStudyMembersResponse;
Expand All @@ -32,16 +30,14 @@ public class GetStudyDetailService {

private final StudyRepository studyRepository;
private final StudyCategoryRepository studyCategoryRepository;
private final StudyStatsRepository studyStatsRepository;
private final StudyMemberRepository studyMemberRepository;
private final StudyViewCountService studyViewCountService;
private final GetMemberInfoPort getMemberInfoPort;

public GetStudyInfoResponse getStudyInfo(long studyId, long viewerId) {
Study study = findStudy(studyId);
StudyStats stats = findStudyStats(studyId);
List<Category> categories = findCategories(studyId);
Statistics statistics = buildStatistics(study, stats, studyId, viewerId);
Statistics statistics = buildStatistics(study, studyId, viewerId);

return toStudyInfoResponse(study, categories, statistics);
}
Expand All @@ -58,23 +54,19 @@ private Study findStudy(long studyId) {
return studyRepository.getStudyById(studyId);
}

private StudyStats findStudyStats(long studyId) {
return studyStatsRepository.getByStudyId(studyId);
}

private List<Category> findCategories(long studyId) {
return studyCategoryRepository.findAllByStudyId(studyId).stream()
.map(StudyCategory::getCategory)
.toList();
}

private Statistics buildStatistics(Study study, StudyStats stats, long studyId, long viewerId) {
long displayViewCount = studyViewCountService.calculateDisplayViewCount(stats, studyId,
private Statistics buildStatistics(Study study, long studyId, long viewerId) {
long displayViewCount = studyViewCountService.calculateDisplayViewCount(study, studyId,
viewerId);
return Statistics.of(
study.getMaxMembers(),
study.getCurrentMembers(),
stats.getLikeCount(),
study.getLikeCount(),
displayViewCount
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package kr.spot.study.application.query;

import kr.spot.study.domain.associations.StudyStats;
import kr.spot.study.domain.Study;
import kr.spot.view.ViewAbuseGuard;
import kr.spot.view.ViewCounter;
import kr.spot.view.ViewableType;
Expand All @@ -16,8 +16,8 @@ public class StudyViewCountService {
private final ViewCounter viewCounter;
private final ViewAbuseGuard viewAbuseGuard;

public long calculateDisplayViewCount(StudyStats stats, long studyId, long viewerId) {
long baseViewCount = stats.getViewCount();
public long calculateDisplayViewCount(Study study, long studyId, long viewerId) {
long baseViewCount = study.getViewCount();
long viewDelta = getViewDeltaFromCounter(studyId, viewerId);
return baseViewCount + viewDelta;
}
Expand Down
6 changes: 5 additions & 1 deletion modules/study/src/main/java/kr/spot/study/domain/Study.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ public class Study extends BaseEntity {
@Column(nullable = false)
private Boolean isOnline = false;

private Long viewCount;

private Long likeCount;

public static Study of(Long id, Long leaderId, String name, Integer maxMembers, Fee fee,
String description) {
return of(id, leaderId, name, maxMembers, fee, null, description, false);
Expand All @@ -75,7 +79,7 @@ public static Study of(Long id, Long leaderId, String name, Integer maxMembers,
validateStudyNameIsNotBlank(name);
validateMaxMembers(maxMembers);
return new Study(id, leaderId, name, maxMembers, CURRENT_MEMBERS, fee, imageUrl, description,
RecruitingStatus.RECRUITING, isOnline != null && isOnline);
RecruitingStatus.RECRUITING, isOnline != null && isOnline, 0L, 0L);
}

private static void validateStudyNameIsNotBlank(String name) {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package kr.spot.study.infrastructure.batch;

import kr.spot.study.infrastructure.jpa.associations.StudyStatsRepository;
import kr.spot.study.infrastructure.jpa.StudyRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
Expand All @@ -12,11 +12,11 @@
@RequiredArgsConstructor
public class StudyViewFlusher {

private final StudyStatsRepository studyStatsRepository;
private final StudyRepository studyRepository;

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateViewCount(long studyId, long delta) {
studyStatsRepository.increaseViewBy(studyId, delta);
studyRepository.increaseViewBy(studyId, delta);
log.debug("스터디 조회수 DB 업데이트: studyId={}, delta={}", studyId, delta);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
import kr.spot.study.domain.Study;
import kr.spot.study.domain.enums.RecruitingStatus;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface StudyRepository extends JpaRepository<Study, Long> {

Expand All @@ -16,4 +19,21 @@ default Study getStudyById(Long studyId) {
long countByLeaderIdAndRecruitingStatus(long leaderId, RecruitingStatus recruitingStatus);

boolean existsByLeaderId(long leaderId);

@Modifying
@Query("""
update Study s
set s.viewCount = s.viewCount + :delta,
s.updatedAt = CURRENT_TIMESTAMP
where s.id = :studyId
""")
int increaseViewBy(@Param("studyId") long studyId, @Param("delta") long delta);

@Modifying
@Query("update Study s set s.likeCount = s.likeCount + 1 where s.id = :studyId")
int increaseLike(@Param("studyId") long studyId);

@Modifying
@Query("update Study s set s.likeCount = case when s.likeCount > 0 then s.likeCount - 1 else 0 end where s.id = :studyId")
int decreaseLike(@Param("studyId") long studyId);
}

This file was deleted.

Loading