diff --git a/src/main/java/kr/KWGraduate/BookPharmacy/domain/book/domain/InterestRecommend.java b/src/main/java/kr/KWGraduate/BookPharmacy/domain/book/domain/InterestRecommend.java index 6c4ccec7..3d9b92c4 100644 --- a/src/main/java/kr/KWGraduate/BookPharmacy/domain/book/domain/InterestRecommend.java +++ b/src/main/java/kr/KWGraduate/BookPharmacy/domain/book/domain/InterestRecommend.java @@ -22,4 +22,9 @@ public class InterestRecommend { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "book_id") private Book book; + + public InterestRecommend(Book b) { + this.middleCategory = b.getMiddleCategory(); + this.book = b; + } } diff --git a/src/main/java/kr/KWGraduate/BookPharmacy/domain/book/repository/BookRepository.java b/src/main/java/kr/KWGraduate/BookPharmacy/domain/book/repository/BookRepository.java index 2be9559d..aa65018b 100644 --- a/src/main/java/kr/KWGraduate/BookPharmacy/domain/book/repository/BookRepository.java +++ b/src/main/java/kr/KWGraduate/BookPharmacy/domain/book/repository/BookRepository.java @@ -4,6 +4,7 @@ import kr.KWGraduate.BookPharmacy.domain.book.dto.response.BookSearchResponseDto; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; @@ -76,4 +77,10 @@ public interface BookRepository extends JpaRepository { "where (LOWER(b.title) like %:searchWord% or LOWER(b.author) like %:searchWord%) and ki.name in :names") Page findPagingBySearchWordAndKeyword(@Param("searchWord") String searchWord, @Param("names") List keywordNameList, Pageable pageable); + + @Query("select b from Book b inner join ReadExperience re on b.id = re.book.id " + + "join fetch b.middleCategory m " + + "where m.id = :categoryId group by b.id " + + "order by count(re.id) desc") + Slice findPopularByCategory(@Param("categoryId") Long categoryId, Pageable pageable); } diff --git a/src/main/java/kr/KWGraduate/BookPharmacy/domain/book/repository/InterestRecommendRepository.java b/src/main/java/kr/KWGraduate/BookPharmacy/domain/book/repository/InterestRecommendRepository.java index f86be9bc..ab571939 100644 --- a/src/main/java/kr/KWGraduate/BookPharmacy/domain/book/repository/InterestRecommendRepository.java +++ b/src/main/java/kr/KWGraduate/BookPharmacy/domain/book/repository/InterestRecommendRepository.java @@ -11,8 +11,16 @@ public interface InterestRecommendRepository extends JpaRepository { - @EntityGraph(attributePaths = {"book"}) - @Query("select ir from InterestRecommend ir join fetch ir.middleCategory mc where mc.id in :categoryIdList") + @Query(value = "select ir.* from book_pharmacy_local.interest_recommend as ir " + + "inner join book_pharmacy_local.book as b on ir.book_id = b.book_id " + + "order by RAND()", nativeQuery = true) + List findRandAll(Pageable pageable); + + @Query(value = "select ir.* from book_pharmacy_local.interest_recommend as ir " + + "inner join book_pharmacy_local.book as b on ir.book_id = b.book_id " + + "inner join book_pharmacy_local.categories as c on ir.category_id = c.category_id " + + "where c.category_id in :categoryIdList order by RAND()" + , nativeQuery = true) List findByInterestList(@Param("categoryIdList") List categoryIdList, Pageable pageable); } \ No newline at end of file diff --git a/src/main/java/kr/KWGraduate/BookPharmacy/domain/book/service/RecommendService.java b/src/main/java/kr/KWGraduate/BookPharmacy/domain/book/service/RecommendService.java index b389cba8..aff8c0be 100644 --- a/src/main/java/kr/KWGraduate/BookPharmacy/domain/book/service/RecommendService.java +++ b/src/main/java/kr/KWGraduate/BookPharmacy/domain/book/service/RecommendService.java @@ -1,14 +1,14 @@ package kr.KWGraduate.BookPharmacy.domain.book.service; +import kr.KWGraduate.BookPharmacy.domain.book.domain.Book; import kr.KWGraduate.BookPharmacy.domain.book.domain.ClientRecommend; import kr.KWGraduate.BookPharmacy.domain.book.domain.InterestRecommend; import kr.KWGraduate.BookPharmacy.domain.book.dto.response.BoardBasedRecommendDto; import kr.KWGraduate.BookPharmacy.domain.book.dto.response.BookBasedRecommendDto; import kr.KWGraduate.BookPharmacy.domain.book.dto.response.ClientBasedRecommendDto; -import kr.KWGraduate.BookPharmacy.domain.book.repository.BoardRecommendRepository; -import kr.KWGraduate.BookPharmacy.domain.book.repository.BookRecommendRepository; -import kr.KWGraduate.BookPharmacy.domain.book.repository.ClientRecommendRepository; -import kr.KWGraduate.BookPharmacy.domain.book.repository.InterestRecommendRepository; +import kr.KWGraduate.BookPharmacy.domain.book.repository.*; +import kr.KWGraduate.BookPharmacy.domain.category.domain.Categories; +import kr.KWGraduate.BookPharmacy.domain.category.repository.CategoryRepository; import kr.KWGraduate.BookPharmacy.domain.client.domain.Client; import kr.KWGraduate.BookPharmacy.domain.client.repository.ClientRepository; import kr.KWGraduate.BookPharmacy.domain.interest.domain.Interest; @@ -37,6 +37,8 @@ public class RecommendService { private final InterestRecommendRepository interestRecommendRepository; private final ClientRepository clientRepository; private final ReadExperienceRepository readExperienceRepository; + private final CategoryRepository categoryRepository; + private final BookRepository bookRepository; public List getClientBasedAiPrescription(AuthenticationAdapter authentication){ String username = authentication.getUsername(); @@ -125,6 +127,25 @@ public List getBookBasedRecommend(String isbn){ .collect(Collectors.toList()); } + // 스케쥴러에 의해 관심사 추천 도서를 등록하는 함수 + public void setInterestRecommend() { + + interestRecommendRepository.deleteAll(); + interestRecommendRepository.flush(); + + List childCategories = categoryRepository.findChildCategories(); + + PageRequest pageRequest = PageRequest.of(0, 30); + + for (Categories category: childCategories) { + Long categoryId = category.getId(); + List popularBookList = bookRepository.findPopularByCategory(categoryId, pageRequest).getContent(); + List interestRecommendList = popularBookList.stream() + .map(book -> new InterestRecommend(book)).collect(Collectors.toList()); + interestRecommendRepository.saveAll(interestRecommendList); + } + } + private List getInterestRecommend(String username, Pageable pageable) { List interestList = interestRepository.findByLoginId(username); // 유저의 관심사리스트 @@ -132,10 +153,10 @@ private List getInterestRecommend(String username, Pageable p if(interestList.isEmpty()) // 유저가 관심사를 하나도 등록하지 않았을 경우 { - interestRecommend = interestRecommendRepository.findAll(pageable).getContent(); + interestRecommend = interestRecommendRepository.findRandAll(pageable); }else{ - List interestIdList = interestList.stream().map(interest -> interest.getId()).collect(Collectors.toList()); + List interestIdList = interestList.stream().map(interest -> interest.getCategory().getId()).collect(Collectors.toList()); interestRecommend = interestRecommendRepository.findByInterestList(interestIdList, pageable); } diff --git a/src/main/java/kr/KWGraduate/BookPharmacy/domain/interest/repository/InterestRepository.java b/src/main/java/kr/KWGraduate/BookPharmacy/domain/interest/repository/InterestRepository.java index 3888b135..d032359b 100644 --- a/src/main/java/kr/KWGraduate/BookPharmacy/domain/interest/repository/InterestRepository.java +++ b/src/main/java/kr/KWGraduate/BookPharmacy/domain/interest/repository/InterestRepository.java @@ -4,6 +4,7 @@ import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import java.util.List; @@ -13,5 +14,5 @@ public interface InterestRepository extends JpaRepository { // 유저의 아이디로 관심사를 조회함 @EntityGraph(attributePaths = {"category"}) @Query("select i from Interest i join fetch i.client c where c.loginId = :loginId") - List findByLoginId(String loginId); + List findByLoginId(@Param("loginId") String loginId); } diff --git a/src/main/java/kr/KWGraduate/BookPharmacy/domain/readexperience/domain/ReadExperience.java b/src/main/java/kr/KWGraduate/BookPharmacy/domain/readexperience/domain/ReadExperience.java index 7a4481ac..d29f3909 100644 --- a/src/main/java/kr/KWGraduate/BookPharmacy/domain/readexperience/domain/ReadExperience.java +++ b/src/main/java/kr/KWGraduate/BookPharmacy/domain/readexperience/domain/ReadExperience.java @@ -15,7 +15,7 @@ @Table(indexes = { @Index(name = "read_experience_index", columnList = "book_id, client_id", unique = true) // 중복된 독서경험이 추가되지 않도록 하기 위함 }) -public class ReadExperience extends BaseTimeEntity { +public class ReadExperience { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "read_experience_id") diff --git a/src/main/java/kr/KWGraduate/BookPharmacy/global/common/service/BookSchedulerService.java b/src/main/java/kr/KWGraduate/BookPharmacy/global/common/service/BookSchedulerService.java index a7ed903b..3bf867b6 100644 --- a/src/main/java/kr/KWGraduate/BookPharmacy/global/common/service/BookSchedulerService.java +++ b/src/main/java/kr/KWGraduate/BookPharmacy/global/common/service/BookSchedulerService.java @@ -1,6 +1,7 @@ package kr.KWGraduate.BookPharmacy.global.common.service; import kr.KWGraduate.BookPharmacy.domain.book.service.BestSellerBookService; +import kr.KWGraduate.BookPharmacy.domain.book.service.RecommendService; import lombok.RequiredArgsConstructor; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @@ -12,9 +13,15 @@ public class BookSchedulerService { private final BestSellerBookService bestSellerBookService; + private final RecommendService recommendService; @Scheduled(cron = "0 0 0 * * *", zone = "Asia/Seoul") // 매일 서울기준, 00시 00분 00초에 실행 public void setBestSeller() { bestSellerBookService.setBestSellerBooks(); } + + @Scheduled(cron = "1 0 0 * * *", zone = "Asia/Seoul") // 매일 서울기준, 00시 00분 00초에 실행 + public void setInterestRecommend() { + recommendService.setInterestRecommend(); + } } diff --git a/submodule-config b/submodule-config index 219fc8a0..5328dfbf 160000 --- a/submodule-config +++ b/submodule-config @@ -1 +1 @@ -Subproject commit 219fc8a04b3ab0eee93e8fc7ab3c33bbfe56f2e9 +Subproject commit 5328dfbfee3248c59072c94cf110fa58b83a105d