From a146e2e7cb4c7ae860ef5b00e0f062266853a22d Mon Sep 17 00:00:00 2001 From: HyunJun Mun <137624597+Mouon@users.noreply.github.com> Date: Wed, 14 Feb 2024 21:54:58 +0900 Subject: [PATCH] =?UTF-8?q?Feat=20:=20CHAT-290-=EC=BA=98=EB=A6=B0=EB=8D=94?= =?UTF-8?q?-=EC=A1=B0=ED=9A=8C-API-=EC=88=98=EC=A0=95=20(#49)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Feat : TypedQuery 작성위해 의존추가 * Feat : TypedQuery 작성위해 의존추가 * Feat : DTO 변경 * Feat : 레포지토리 작성 * Feat : 리펙토링 기존 DiaryList 레포지토리의 쿼리 활용 위해 일반적인 쿼리는 분리후 재사용 * Feat : 서비스계층 추가적인 쿼리 작성없이 일기조회 기능 구현 기본적인 기능 구현 * Feat : 컨트롤러 걔층 반환하는 DTO 변경으로인한 수정 소요 * Fix : 쿼리수정 User가 날짜에있으면 조회가 안되는 버그가있어 쿼리 수정 * Fix : findMostActiveSender 매서드 수정 쿼리를 통해 데이터를 먼저 걸러와서, 불필요한 데이터 조회 안함 + 필요없는 조건문 제거 * Fix : findMostActiveSender 수정 MAX를 이용해 Sender 별로 가장 최근값을 비교해 내림차순해서 정렬하게 함 --- build.gradle | 2 + .../calendar/CalendarInquiryController.java | 11 +-- ...e.java => CalendarInquiryResponseDTO.java} | 7 +- .../chatdiary/dto/DateInquiryResponse.java | 18 ----- .../repository/CalendarInquiryRepository.java | 67 ------------------- .../repository/diary/DiaryListRepository.java | 50 ++++++++------ .../repository/statics/SenderRepository.java | 23 +++++++ .../calendar/CalendarInquiryService.java | 53 ++++++++------- 8 files changed, 92 insertions(+), 139 deletions(-) rename src/main/java/com/kuit/chatdiary/dto/{CalendarInquiryResponse.java => CalendarInquiryResponseDTO.java} (66%) delete mode 100644 src/main/java/com/kuit/chatdiary/dto/DateInquiryResponse.java delete mode 100644 src/main/java/com/kuit/chatdiary/repository/CalendarInquiryRepository.java diff --git a/build.gradle b/build.gradle index aa33729a..409076d9 100644 --- a/build.gradle +++ b/build.gradle @@ -22,6 +22,8 @@ repositories { } dependencies { + + implementation 'org.hibernate:hibernate-core:6.4.2.Final' implementation 'org.json:json:20220320' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' diff --git a/src/main/java/com/kuit/chatdiary/controller/calendar/CalendarInquiryController.java b/src/main/java/com/kuit/chatdiary/controller/calendar/CalendarInquiryController.java index 49f4a85a..c6508695 100644 --- a/src/main/java/com/kuit/chatdiary/controller/calendar/CalendarInquiryController.java +++ b/src/main/java/com/kuit/chatdiary/controller/calendar/CalendarInquiryController.java @@ -1,8 +1,6 @@ package com.kuit.chatdiary.controller.calendar; -import com.kuit.chatdiary.domain.Sender; -import com.kuit.chatdiary.dto.CalendarInquiryResponse; -import com.kuit.chatdiary.dto.DateInquiryResponse; +import com.kuit.chatdiary.dto.CalendarInquiryResponseDTO; import com.kuit.chatdiary.service.calendar.CalendarInquiryService; import lombok.extern.slf4j.Slf4j; import org.springframework.format.annotation.DateTimeFormat; @@ -12,11 +10,8 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import java.time.LocalDate; -import java.time.LocalDateTime; import java.time.YearMonth; import java.util.List; -import java.util.Map; @RestController @RequestMapping("chat") @@ -27,11 +22,11 @@ public CalendarInquiryController(CalendarInquiryService calendarInquiryService) this.calendarInquiryService = calendarInquiryService; } @GetMapping("/chat") - public ResponseEntity> getChatExistsByMonth( + public ResponseEntity> getChatExistsByMonth( @RequestParam("memberId") long memberId, @RequestParam("month") @DateTimeFormat(pattern = "yyyy-MM") YearMonth month) { - List chatExistsByMonth = calendarInquiryService.existsChatByMonth(memberId, month); + List chatExistsByMonth = calendarInquiryService.getCalendarInquiryResponses(memberId,month); return ResponseEntity.ok(chatExistsByMonth); } } \ No newline at end of file diff --git a/src/main/java/com/kuit/chatdiary/dto/CalendarInquiryResponse.java b/src/main/java/com/kuit/chatdiary/dto/CalendarInquiryResponseDTO.java similarity index 66% rename from src/main/java/com/kuit/chatdiary/dto/CalendarInquiryResponse.java rename to src/main/java/com/kuit/chatdiary/dto/CalendarInquiryResponseDTO.java index 6eaf1d91..059798d1 100644 --- a/src/main/java/com/kuit/chatdiary/dto/CalendarInquiryResponse.java +++ b/src/main/java/com/kuit/chatdiary/dto/CalendarInquiryResponseDTO.java @@ -3,12 +3,15 @@ import com.kuit.chatdiary.domain.Sender; import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; @Getter @Setter @AllArgsConstructor -public class CalendarInquiryResponse { +@NoArgsConstructor +public class CalendarInquiryResponseDTO { + private String dates; private Sender sender; private boolean exists; -} \ No newline at end of file +} diff --git a/src/main/java/com/kuit/chatdiary/dto/DateInquiryResponse.java b/src/main/java/com/kuit/chatdiary/dto/DateInquiryResponse.java deleted file mode 100644 index 3a16aee5..00000000 --- a/src/main/java/com/kuit/chatdiary/dto/DateInquiryResponse.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.kuit.chatdiary.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -import java.time.LocalDate; -import java.util.List; - -@Getter -@Setter -@AllArgsConstructor -@NoArgsConstructor -public class DateInquiryResponse { - private List dates; - private List responses; -} diff --git a/src/main/java/com/kuit/chatdiary/repository/CalendarInquiryRepository.java b/src/main/java/com/kuit/chatdiary/repository/CalendarInquiryRepository.java deleted file mode 100644 index 6bd68884..00000000 --- a/src/main/java/com/kuit/chatdiary/repository/CalendarInquiryRepository.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.kuit.chatdiary.repository; - -import com.kuit.chatdiary.domain.Sender; -import com.kuit.chatdiary.dto.CalendarInquiryResponse; -import jakarta.persistence.EntityManager; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Repository; -import java.time.LocalDate; -import java.time.LocalTime; -import java.time.YearMonth; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@Repository -@Slf4j -public class CalendarInquiryRepository { - private final EntityManager em; - - public CalendarInquiryRepository(EntityManager em) { - this.em = em; - } - - public Map> existsChatByMonth(long memberId, YearMonth month) { - LocalDate startOfMonth = month.atDay(1); - LocalDate endOfMonth = month.atEndOfMonth(); - Map> chatExistsByMonth = new HashMap<>(); - - for (LocalDate date = startOfMonth; !date.isAfter(endOfMonth); date = date.plusDays(1)) { - List dailyResponses = new ArrayList<>(); - for (Sender sender : Sender.values()) { - dailyResponses.add(new CalendarInquiryResponse(sender, false)); - } - chatExistsByMonth.put(date, dailyResponses); - } - - List results = em.createQuery( - "SELECT CAST(c.createAt AS date), c.sender, COUNT(*) " + - "FROM chat c WHERE c.member.userId = :userId " + - "AND c.createAt BETWEEN :startOfMonth AND :endOfMonth " + - "GROUP BY CAST(c.createAt AS date), c.sender", Object[].class) - .setParameter("userId", memberId) - .setParameter("startOfMonth", startOfMonth.atStartOfDay()) - .setParameter("endOfMonth", endOfMonth.atTime(LocalTime.MAX)) - .getResultList(); - - log.info("Query results: {}", results); - for (Object[] result : results) { - LocalDate date = ((java.sql.Date) result[0]).toLocalDate(); - Sender sender = (Sender) result[1]; - Long count = (Long) result[2]; - - List dailyResponses = chatExistsByMonth.get(date); - - if (dailyResponses != null) { - for (CalendarInquiryResponse response : dailyResponses) { - if (response.getSender() == sender) { - response.setExists(count > 0); - break; - } - } - } - } - return chatExistsByMonth; - } -} diff --git a/src/main/java/com/kuit/chatdiary/repository/diary/DiaryListRepository.java b/src/main/java/com/kuit/chatdiary/repository/diary/DiaryListRepository.java index cb6850e0..11ccd0b1 100644 --- a/src/main/java/com/kuit/chatdiary/repository/diary/DiaryListRepository.java +++ b/src/main/java/com/kuit/chatdiary/repository/diary/DiaryListRepository.java @@ -16,31 +16,39 @@ @Repository public class DiaryListRepository { - private final EntityManager em; - public DiaryListRepository(EntityManager em) { + private final EntityManager em; + public DiaryListRepository(EntityManager em) { this.em = em; } - /** 우선 쿼리 세개 날리기.. */ - public List inquiryDiaryRange(Long userId, Date startDate, Date endDate) { - List diaries = em.createQuery("SELECT d FROM diary d WHERE d.member.userId = :userId AND d.diaryDate BETWEEN :startDate AND :endDate", Diary.class) - .setParameter("userId", userId) - .setParameter("startDate", startDate, TemporalType.DATE) - .setParameter("endDate", endDate, TemporalType.DATE) - .getResultList(); - - return diaries.stream().map(diary -> { - List diaryPhotos = em.createQuery("SELECT dp FROM diaryphoto dp WHERE dp.diary = :diary", DiaryPhoto.class) - .setParameter("diary", diary) - .getResultList(); - List diaryTags = em.createQuery("SELECT dt FROM diarytag dt WHERE dt.diary = :diary", DiaryTag.class) - .setParameter("diary", diary) - .getResultList(); - - return new DiaryListResponseDTO(diary, diaryPhotos, diaryTags); - }).collect(Collectors.toList()); - } + /** + * 중복되는 쿼리 따로 분리 + * 재사용성 높이기 + */ + public List getDiaries(Long userId, Date startDate, Date endDate) { + return em.createQuery("SELECT d FROM diary d WHERE d.member.userId = :userId AND d.diaryDate BETWEEN :startDate AND :endDate", Diary.class) + .setParameter("userId", userId) + .setParameter("startDate", startDate, TemporalType.DATE) + .setParameter("endDate", endDate, TemporalType.DATE) + .getResultList(); + } + + public List inquiryDiaryRange(Long userId, Date startDate, Date endDate) { + return getDiaries(userId, startDate, endDate).stream() + .map(diary -> { + List diaryPhotos = em.createQuery("SELECT dp FROM diaryphoto dp WHERE dp.diary = :diary", DiaryPhoto.class) + .setParameter("diary", diary) + .getResultList(); + List diaryTags = em.createQuery("SELECT dt FROM diarytag dt WHERE dt.diary = :diary", DiaryTag.class) + .setParameter("diary", diary) + .getResultList(); + + return new DiaryListResponseDTO(diary, diaryPhotos, diaryTags); + }).collect(Collectors.toList()); + } + + } diff --git a/src/main/java/com/kuit/chatdiary/repository/statics/SenderRepository.java b/src/main/java/com/kuit/chatdiary/repository/statics/SenderRepository.java index 68db9e4e..12ec5b1a 100644 --- a/src/main/java/com/kuit/chatdiary/repository/statics/SenderRepository.java +++ b/src/main/java/com/kuit/chatdiary/repository/statics/SenderRepository.java @@ -1,6 +1,8 @@ package com.kuit.chatdiary.repository.statics; +import com.kuit.chatdiary.domain.Sender; import jakarta.persistence.EntityManager; +import jakarta.persistence.TypedQuery; import org.springframework.stereotype.Repository; import java.sql.Date; @@ -27,4 +29,25 @@ public List countChatsBySenderAndDate(Long userId, Date startDate, Dat .setParameter("endDate", endDate) .getResultList(); } + + public Sender findMostActiveSender(long userId, Date diaryDate) { + String jpql = "SELECT c.sender FROM chat c " + + "WHERE c.member.id = :memberId AND c.sender != :sender " + + "AND c.createAt >= :startDate AND c.createAt < :endDate " + + "GROUP BY c.sender " + + "ORDER BY COUNT(c) DESC, MAX(c.createAt) DESC"; + TypedQuery query = em.createQuery(jpql, Sender.class) + .setParameter("memberId", userId) + .setParameter("sender", Sender.USER) + .setParameter("startDate", diaryDate.toLocalDate().atStartOfDay()) + .setParameter("endDate", diaryDate.toLocalDate().plusDays(1).atStartOfDay()) + .setMaxResults(1); + List resultList = query.getResultList(); + + if (!resultList.isEmpty()) { + return resultList.get(0); + } else { + return null; + } + } } \ No newline at end of file diff --git a/src/main/java/com/kuit/chatdiary/service/calendar/CalendarInquiryService.java b/src/main/java/com/kuit/chatdiary/service/calendar/CalendarInquiryService.java index ac84db2d..c0a65d25 100644 --- a/src/main/java/com/kuit/chatdiary/service/calendar/CalendarInquiryService.java +++ b/src/main/java/com/kuit/chatdiary/service/calendar/CalendarInquiryService.java @@ -1,43 +1,50 @@ package com.kuit.chatdiary.service.calendar; +import com.kuit.chatdiary.domain.Diary; import com.kuit.chatdiary.domain.Sender; -import com.kuit.chatdiary.dto.CalendarInquiryResponse; -import com.kuit.chatdiary.dto.DateInquiryResponse; +import com.kuit.chatdiary.dto.CalendarInquiryResponseDTO; +import com.kuit.chatdiary.repository.diary.DiaryListRepository; +import com.kuit.chatdiary.repository.statics.SenderRepository; +import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; -import com.kuit.chatdiary.repository.CalendarInquiryRepository; +import org.springframework.transaction.annotation.Transactional; +import java.sql.Date; import java.time.LocalDate; import java.time.YearMonth; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; @Service +@RequiredArgsConstructor +@Transactional(readOnly = true) public class CalendarInquiryService { - private final CalendarInquiryRepository calendarInquiryRepository; + private final DiaryListRepository diaryListRepository; + private final SenderRepository senderRepository; - public CalendarInquiryService(CalendarInquiryRepository calendarInquiryRepository) { - this.calendarInquiryRepository = calendarInquiryRepository; + public boolean existsDiary(long memberId, java.util.Date diaryDate) { + List diaries = diaryListRepository.getDiaries(memberId, diaryDate, diaryDate); + return !diaries.isEmpty(); } - public List existsChatByMonth(long memberId, YearMonth month) { - Map> chatExistsByMonth = calendarInquiryRepository.existsChatByMonth(memberId, month); - - List list = new ArrayList<>(); - /**각 요소들에 대해 반복*/ - for(Map.Entry> entry : chatExistsByMonth.entrySet()) { - List dates = new ArrayList<>(); - /**키 값 받아서 리스트에 저장*/ - dates.add(entry.getKey()); - DateInquiryResponse response = new DateInquiryResponse(dates, entry.getValue()); - list.add(response); - } - return list; - } + public List getCalendarInquiryResponses(long memberId, LocalDate startDate, LocalDate endDate) { + List responses = new ArrayList<>(); + for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) { + Date diaryDate = Date.valueOf(date); + boolean exists = existsDiary(memberId, diaryDate); + Sender sender = senderRepository.findMostActiveSender(memberId, diaryDate); + responses.add(new CalendarInquiryResponseDTO(diaryDate.toString(), sender, exists)); + } + return responses; + } -} \ No newline at end of file + public List getCalendarInquiryResponses(long memberId, YearMonth month) { + LocalDate startDate = month.atDay(1); + LocalDate endDate = month.atEndOfMonth(); + return getCalendarInquiryResponses(memberId, startDate, endDate); + } +}