From 01197c1fba5194e273d7d76c838c9ded4b94b106 Mon Sep 17 00:00:00 2001 From: Munhangyeol Date: Sun, 5 Jan 2025 17:11:52 +0900 Subject: [PATCH] =?UTF-8?q?Refactor:=20count=EC=97=90=20=EC=9D=B8=EB=8D=B1?= =?UTF-8?q?=EC=8A=A4=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dev-route/build.gradle | 9 +- .../devroute/DevRouteApplication.java | 3 + .../devroute/dataloader/VideoDataLoader.java | 137 +++++++++--------- .../global/config/SecurityConfig.java | 1 + .../service/RecruitmentUpdateService.java | 2 +- .../devroute/video/QueryDslConfig.java | 20 +++ .../Repository/VideoQueryRepository.java | 37 +++++ .../video/Repository/VideoRepository.java | 9 +- .../devroute/video/domain/Videos.java | 11 +- .../video/fetcher/YoutubeVideoFetcher.java | 1 - .../devroute/video/service/VideoService.java | 46 ++++-- .../main/resources/application-dev.properties | 3 +- .../src/main/resources/application.properties | 2 +- .../devroute/video/VideoServiceTest.java | 13 ++ 14 files changed, 195 insertions(+), 99 deletions(-) create mode 100644 dev-route/src/main/java/com/teamdevroute/devroute/video/QueryDslConfig.java create mode 100644 dev-route/src/main/java/com/teamdevroute/devroute/video/Repository/VideoQueryRepository.java diff --git a/dev-route/build.gradle b/dev-route/build.gradle index 4a2442b..eed0b5b 100644 --- a/dev-route/build.gradle +++ b/dev-route/build.gradle @@ -56,6 +56,11 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-actuator' implementation 'io.micrometer:micrometer-registry-prometheus' + implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' + annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta" + annotationProcessor "jakarta.annotation:jakarta.annotation-api" + annotationProcessor "jakarta.persistence:jakarta.persistence-api" + } tasks.named('test') { @@ -70,6 +75,8 @@ task copySecret(type: Copy) { } into ('./src/main/resources') } - +clean { + delete file('src/main/generated') +} diff --git a/dev-route/src/main/java/com/teamdevroute/devroute/DevRouteApplication.java b/dev-route/src/main/java/com/teamdevroute/devroute/DevRouteApplication.java index 8edd3bd..825bcea 100644 --- a/dev-route/src/main/java/com/teamdevroute/devroute/DevRouteApplication.java +++ b/dev-route/src/main/java/com/teamdevroute/devroute/DevRouteApplication.java @@ -1,13 +1,16 @@ package com.teamdevroute.devroute; +import com.teamdevroute.devroute.video.QueryDslConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Import; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; import org.springframework.scheduling.annotation.EnableScheduling; @EnableJpaAuditing @EnableScheduling @SpringBootApplication +//@Import(QueryDslConfig.class) public class DevRouteApplication { public static void main(String[] args) { diff --git a/dev-route/src/main/java/com/teamdevroute/devroute/dataloader/VideoDataLoader.java b/dev-route/src/main/java/com/teamdevroute/devroute/dataloader/VideoDataLoader.java index 9f75c7f..5bd8ee5 100644 --- a/dev-route/src/main/java/com/teamdevroute/devroute/dataloader/VideoDataLoader.java +++ b/dev-route/src/main/java/com/teamdevroute/devroute/dataloader/VideoDataLoader.java @@ -38,74 +38,79 @@ public void loadVideoData(){ Long count=0L; for (PlatformName platformname : PlatformName.values()) { for (TechnologyStackName value : TechnologyStackName.values()) { - switch (platformname) { - case Inflearn: - if(count%3==0) - createVideo( - 0L, platformname+"의 유명한 "+value+" 비디오", - "https://www.inflearn.com/course/%EA%B9%A1%EC%83%98%EC%9D%98-%EC%8C%A9%EC%B4%88%EB%B3%B4-%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-part5?attributionToken=ChM1ODg3MTk1NTc2ODEzOTQ3ODQwEA0aI3JlY29tbWVuZGVfcmVjb21tZW5kZV8xNzAyNTI2NDM0MDY2IhdyZWNvbW1lbmRlZC1mb3IteW91LWN2cigAOij38dES-vHRErTx0RKy8dESqfLREq3y0RKP8tESjPLREr7y0RK78tES" - , - "https://cdn.inflearn.com/public/courses/334276/cover/87c0dc98-efe3-47ab-82ce-225a45c2e7a7/334276.png?w=420 ", - count, String.valueOf(value), String.valueOf(platformname) - ); - if(count%3==1) - createVideo( - 0L, platformname+"의 유명한 "+value+" 비디오", - "https://www.inflearn.com/course/vue-3-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0?attributionToken=ChQxNDU5NjE4NDYyMDA0NTA0Mzc3NBANGiNyZWNvbW1lbmRlX3JlY29tbWVuZGVfMTcwMjUyNjQzNDA2NiIXcmVjb21tZW5kZWQtZm9yLXlvdS1jdnIoADoo-vHRErTx0RKy8dESu_LREozy0RL38dESj_LREqny0RKt8tESvvLREg" - , - "https://cdn.inflearn.com/public/courses/332010/cover/fffd02eb-685e-44ab-aa0d-6788349338c5/332010-eng.png?w=420", - count, String.valueOf(value), String.valueOf(platformname) - ); - if(count%3==2) - createVideo( - 0L, platformname+"의 유명한 "+value+" 비디오", - "https://www.inflearn.com/course/amazing-javascript-%EC%9E%85%EB%AC%B8?attributionToken=ChQxNDU5NjE4NDYyMDA0NTA0Mzc3NBANGiNyZWNvbW1lbmRlX3JlY29tbWVuZGVfMTcwMjUyNjQzNDA2NiIXcmVjb21tZW5kZWQtZm9yLXlvdS1jdnIoADoo-vHRErTx0RKy8dESu_LREozy0RL38dESj_LREqny0RKt8tESvvLREg", - "https://cdn.inflearn.com/public/courses/334104/cover/8eafc0d0-1be5-426a-be30-38bb90ccec21/334104.png?w=420" , - count, String.valueOf(value), String.valueOf(platformname) - ); - - case Youtube: - if(count%3==0) - createVideo( - 0L, platformname+"의 유명한 "+value+" 비디오","https://www.youtube.com/watch?v=lYmLUiBAqqM" - ,"https://i.ytimg.com/vi/lYmLUiBAqqM/default.jpg", - count, String.valueOf(value), String.valueOf(platformname) - ); - if(count%3==1) - createVideo( - 0L, platformname+"의 유명한 "+value+" 비디오","https://www.youtube.com/watch?v=lYmLUiBAqqM" - ,"https://i.ytimg.com/vi/lYmLUiBAqqM/default.jpg", - count, String.valueOf(value), String.valueOf(platformname) - ); - if(count%3==2) - createVideo( - 0L, platformname+"의 유명한 "+value+" 비디오","https://www.youtube.com/watch?v=lYmLUiBAqqM" - ,"https://i.ytimg.com/vi/lYmLUiBAqqM/default.jpg", - count, String.valueOf(value), String.valueOf(platformname) - ); - case Udemy: - if(count%3==0) - createVideo( - 0L, platformname+"의 유명한 "+value+" 비디오","https://www.udemy.com/course/javascript-zero-to-expert-the-complete-modern-guide-build-real-apps/" - ,"https://img-c.udemycdn.com/course/125_H/3429704_e81d_4.jpg", - count, String.valueOf(value), String.valueOf(platformname) - ); - if(count%3==1) - createVideo( - 0L, platformname+"의 유명한 "+value+" 비디오","https://www.udemy.com/course/complete-angular-14-course-learn-frontend-development/" - ,"https://img-c.udemycdn.com/course/125_H/4844324_2d2b_4.jpg", - count, String.valueOf(value), String.valueOf(platformname) - ); - if(count%3==2) - createVideo( - 0L, platformname+"의 유명한 "+value+" 비디오","https://www.udemy.com/course/html-css-for-beginer/ " - ,"https://img-c.udemycdn.com/course/125_H/3426600_1577.jpg", - count, String.valueOf(value), String.valueOf(platformname) - ); - count += 1; + while (count < 1000) { + switch (platformname) { + case Inflearn: + if (count % 3 == 0) + createVideo( + 0L, platformname + "의 유명한 " + value + " 비디오", + "https://www.inflearn.com/course/%EA%B9%A1%EC%83%98%EC%9D%98-%EC%8C%A9%EC%B4%88%EB%B3%B4-%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-part5?attributionToken=ChM1ODg3MTk1NTc2ODEzOTQ3ODQwEA0aI3JlY29tbWVuZGVfcmVjb21tZW5kZV8xNzAyNTI2NDM0MDY2IhdyZWNvbW1lbmRlZC1mb3IteW91LWN2cigAOij38dES-vHRErTx0RKy8dESqfLREq3y0RKP8tESjPLREr7y0RK78tES" + , + "https://cdn.inflearn.com/public/courses/334276/cover/87c0dc98-efe3-47ab-82ce-225a45c2e7a7/334276.png?w=420 ", + count, String.valueOf(value), String.valueOf(platformname) + ); + if (count % 3 == 1) + createVideo( + 0L, platformname + "의 유명한 " + value + " 비디오", + "https://www.inflearn.com/course/vue-3-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0?attributionToken=ChQxNDU5NjE4NDYyMDA0NTA0Mzc3NBANGiNyZWNvbW1lbmRlX3JlY29tbWVuZGVfMTcwMjUyNjQzNDA2NiIXcmVjb21tZW5kZWQtZm9yLXlvdS1jdnIoADoo-vHRErTx0RKy8dESu_LREozy0RL38dESj_LREqny0RKt8tESvvLREg" + , + "https://cdn.inflearn.com/public/courses/332010/cover/fffd02eb-685e-44ab-aa0d-6788349338c5/332010-eng.png?w=420", + count, String.valueOf(value), String.valueOf(platformname) + ); + if (count % 3 == 2) + createVideo( + 0L, platformname + "의 유명한 " + value + " 비디오", + "https://www.inflearn.com/course/amazing-javascript-%EC%9E%85%EB%AC%B8?attributionToken=ChQxNDU5NjE4NDYyMDA0NTA0Mzc3NBANGiNyZWNvbW1lbmRlX3JlY29tbWVuZGVfMTcwMjUyNjQzNDA2NiIXcmVjb21tZW5kZWQtZm9yLXlvdS1jdnIoADoo-vHRErTx0RKy8dESu_LREozy0RL38dESj_LREqny0RKt8tESvvLREg", + "https://cdn.inflearn.com/public/courses/334104/cover/8eafc0d0-1be5-426a-be30-38bb90ccec21/334104.png?w=420", + count, String.valueOf(value), String.valueOf(platformname) + ); + break; + + case Youtube: + if (count % 3 == 0) + createVideo( + 0L, platformname + "의 유명한 " + value + " 비디오", "https://www.youtube.com/watch?v=lYmLUiBAqqM" + , "https://i.ytimg.com/vi/lYmLUiBAqqM/default.jpg", + count, String.valueOf(value), String.valueOf(platformname) + ); + if (count % 3 == 1) + createVideo( + 0L, platformname + "의 유명한 " + value + " 비디오", "https://www.youtube.com/watch?v=lYmLUiBAqqM" + , "https://i.ytimg.com/vi/lYmLUiBAqqM/default.jpg", + count, String.valueOf(value), String.valueOf(platformname) + ); + if (count % 3 == 2) + createVideo( + 0L, platformname + "의 유명한 " + value + " 비디오", "https://www.youtube.com/watch?v=lYmLUiBAqqM" + , "https://i.ytimg.com/vi/lYmLUiBAqqM/default.jpg", + count, String.valueOf(value), String.valueOf(platformname) + ); + break; + case Udemy: + if (count % 3 == 0) + createVideo( + 0L, platformname + "의 유명한 " + value + " 비디오", "https://www.udemy.com/course/javascript-zero-to-expert-the-complete-modern-guide-build-real-apps/" + , "https://img-c.udemycdn.com/course/125_H/3429704_e81d_4.jpg", + count, String.valueOf(value), String.valueOf(platformname) + ); + if (count % 3 == 1) + createVideo( + 0L, platformname + "의 유명한 " + value + " 비디오", "https://www.udemy.com/course/complete-angular-14-course-learn-frontend-development/" + , "https://img-c.udemycdn.com/course/125_H/4844324_2d2b_4.jpg", + count, String.valueOf(value), String.valueOf(platformname) + ); + if (count % 3 == 2) + createVideo( + 0L, platformname + "의 유명한 " + value + " 비디오", "https://www.udemy.com/course/html-css-for-beginer/ " + , "https://img-c.udemycdn.com/course/125_H/3426600_1577.jpg", + count, String.valueOf(value), String.valueOf(platformname) + ); + break; + } + count += 1; + } } - } } diff --git a/dev-route/src/main/java/com/teamdevroute/devroute/global/config/SecurityConfig.java b/dev-route/src/main/java/com/teamdevroute/devroute/global/config/SecurityConfig.java index 9579331..e50828b 100644 --- a/dev-route/src/main/java/com/teamdevroute/devroute/global/config/SecurityConfig.java +++ b/dev-route/src/main/java/com/teamdevroute/devroute/global/config/SecurityConfig.java @@ -75,6 +75,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); + configuration.addAllowedOrigin("*"); configuration.addAllowedOrigin("https://devroute.site"); // 필요한 도메인으로 설정하세요 configuration.addAllowedMethod("*"); configuration.addAllowedHeader("*"); diff --git a/dev-route/src/main/java/com/teamdevroute/devroute/recruitment/service/RecruitmentUpdateService.java b/dev-route/src/main/java/com/teamdevroute/devroute/recruitment/service/RecruitmentUpdateService.java index 7cedac5..c6f8249 100644 --- a/dev-route/src/main/java/com/teamdevroute/devroute/recruitment/service/RecruitmentUpdateService.java +++ b/dev-route/src/main/java/com/teamdevroute/devroute/recruitment/service/RecruitmentUpdateService.java @@ -49,7 +49,7 @@ private void fetchAndSaveJobs(String keyword) { String initialUrl = API_URL + accessKey + "&keywords=" + keyword + "&start=0&count=100"; String initialResponse = restTemplate.getForObject(initialUrl, String.class); - + System.out.println(initialResponse); try { if(isMaxApiRequest(objectMapper,initialResponse)) return; diff --git a/dev-route/src/main/java/com/teamdevroute/devroute/video/QueryDslConfig.java b/dev-route/src/main/java/com/teamdevroute/devroute/video/QueryDslConfig.java new file mode 100644 index 0000000..d8ea017 --- /dev/null +++ b/dev-route/src/main/java/com/teamdevroute/devroute/video/QueryDslConfig.java @@ -0,0 +1,20 @@ +package com.teamdevroute.devroute.video; + +import com.querydsl.jpa.impl.JPAQueryFactory; +import jakarta.persistence.EntityManager; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.convert.ReadingConverter; + +import javax.swing.text.html.parser.Entity; + +@Configuration +@RequiredArgsConstructor +public class QueryDslConfig { + private final EntityManager em; + @Bean + public JPAQueryFactory jpaQueryFactory(){ + return new JPAQueryFactory(em); + } +} diff --git a/dev-route/src/main/java/com/teamdevroute/devroute/video/Repository/VideoQueryRepository.java b/dev-route/src/main/java/com/teamdevroute/devroute/video/Repository/VideoQueryRepository.java new file mode 100644 index 0000000..0c8db75 --- /dev/null +++ b/dev-route/src/main/java/com/teamdevroute/devroute/video/Repository/VideoQueryRepository.java @@ -0,0 +1,37 @@ +package com.teamdevroute.devroute.video.Repository; + +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.jpa.impl.JPAQueryFactory; +import com.teamdevroute.devroute.video.domain.Videos; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; + +import java.util.List; + +import static com.teamdevroute.devroute.video.domain.QVideos.videos; + +@Repository +@RequiredArgsConstructor +public class VideoQueryRepository { + private final JPAQueryFactory query; + public List findLectures(String platformName,String techStack){ + return query.select(videos) + .from(videos) + .where(isPlatform(platformName), isTechStack(techStack)) + .fetch(); + } + private BooleanExpression isPlatform(String platformName){ + System.out.println(platformName); + + if(platformName!=null){ + return videos.platformName.eq(platformName); + } + + return null; + } + private BooleanExpression isTechStack(String techStack){ + if(techStack!=null) + return videos.teckStack.eq(techStack); + return null; + } +} diff --git a/dev-route/src/main/java/com/teamdevroute/devroute/video/Repository/VideoRepository.java b/dev-route/src/main/java/com/teamdevroute/devroute/video/Repository/VideoRepository.java index 93ff5de..af1bfee 100644 --- a/dev-route/src/main/java/com/teamdevroute/devroute/video/Repository/VideoRepository.java +++ b/dev-route/src/main/java/com/teamdevroute/devroute/video/Repository/VideoRepository.java @@ -6,17 +6,16 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import java.util.List; import java.util.Optional; public interface VideoRepository extends JpaRepository { + Optional> findByPlatformNameAndTeckStack(String platform_name, String teck_stack); - default Optional> findTop3ByOrderByCountDesc() { - Pageable topThree = PageRequest.of(0, 3, Sort.by("count").descending()); - Page page = findAll(topThree); - return Optional.ofNullable(page.getContent().isEmpty() ? null : page.getContent()); - } + + ListfindTop3ByOrderByCountDesc(); long count(); } diff --git a/dev-route/src/main/java/com/teamdevroute/devroute/video/domain/Videos.java b/dev-route/src/main/java/com/teamdevroute/devroute/video/domain/Videos.java index 6e02aff..1645b11 100644 --- a/dev-route/src/main/java/com/teamdevroute/devroute/video/domain/Videos.java +++ b/dev-route/src/main/java/com/teamdevroute/devroute/video/domain/Videos.java @@ -2,14 +2,8 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import jakarta.persistence.AttributeConverter; -import jakarta.persistence.Column; -import jakarta.persistence.Convert; -import jakarta.persistence.Converter; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import jakarta.persistence.*; + import java.io.IOException; import java.util.Map; import lombok.Builder; @@ -18,6 +12,7 @@ @Entity @Getter //@Setter +@Table(indexes = @Index(name="idx_count",columnList = "count")) public class Videos { @Id diff --git a/dev-route/src/main/java/com/teamdevroute/devroute/video/fetcher/YoutubeVideoFetcher.java b/dev-route/src/main/java/com/teamdevroute/devroute/video/fetcher/YoutubeVideoFetcher.java index f0ff3fb..d79673c 100644 --- a/dev-route/src/main/java/com/teamdevroute/devroute/video/fetcher/YoutubeVideoFetcher.java +++ b/dev-route/src/main/java/com/teamdevroute/devroute/video/fetcher/YoutubeVideoFetcher.java @@ -19,7 +19,6 @@ public YoutubeVideoFetcher(RestTemplate restTemplate) { } public YouTubeApiResponse fetchYoutubeVideos(String value) { -// System.out.println(getYoutubeApiUrl(value)); return restTemplate.getForObject(getYoutubeApiUrl(value), YouTubeApiResponse.class); } diff --git a/dev-route/src/main/java/com/teamdevroute/devroute/video/service/VideoService.java b/dev-route/src/main/java/com/teamdevroute/devroute/video/service/VideoService.java index b3813e9..794a406 100644 --- a/dev-route/src/main/java/com/teamdevroute/devroute/video/service/VideoService.java +++ b/dev-route/src/main/java/com/teamdevroute/devroute/video/service/VideoService.java @@ -1,5 +1,10 @@ package com.teamdevroute.devroute.video.service; +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.core.types.dsl.BooleanOperation; +import com.querydsl.jpa.impl.JPAQueryFactory; +import com.teamdevroute.devroute.global.aop.timetrace.TimeTrace; +import com.teamdevroute.devroute.video.Repository.VideoQueryRepository; import com.teamdevroute.devroute.video.exception.VideoNotFounException; import com.teamdevroute.devroute.video.Repository.TechnologyStackRepository; import com.teamdevroute.devroute.video.Repository.VideoRepository; @@ -15,7 +20,11 @@ import com.teamdevroute.devroute.video.fetcher.InfreanVideoFetcher; import com.teamdevroute.devroute.video.fetcher.UdemyVideoFetcher; import com.teamdevroute.devroute.video.fetcher.YoutubeVideoFetcher; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -27,13 +36,18 @@ import static com.teamdevroute.devroute.video.constans.ApiConstans.UDEMY_API_URL_FRONT_VIDEOID; import static com.teamdevroute.devroute.video.constans.ApiConstans.YOUTUBE_API_URL_FRONT_VIDEOID; +import static com.teamdevroute.devroute.video.domain.QVideos.videos; import static com.teamdevroute.devroute.video.enums.PlatformName.*; @Service @Slf4j @Transactional +@RequiredArgsConstructor public class VideoService { + + private final VideoQueryRepository queryRepository; + private final VideoRepository videoRepository; private final YoutubeVideoFetcher youtubeVideoFetcher; private final UdemyVideoFetcher udemyVideoFetcher; @@ -41,14 +55,7 @@ public class VideoService { private final TechnologyStackRepository technologyStackRepository; - public VideoService(VideoRepository videoRepository, YoutubeVideoFetcher youtubeVideoFetcher, - UdemyVideoFetcher udemyVideoFetcher, InfreanVideoFetcher infreanVideoFetcher, TechnologyStackRepository technologyStackRepository) { - this.videoRepository = videoRepository; - this.youtubeVideoFetcher = youtubeVideoFetcher; - this.udemyVideoFetcher = udemyVideoFetcher; - this.infreanVideoFetcher = infreanVideoFetcher; - this.technologyStackRepository = technologyStackRepository; - } + //매주 토요일에 실행 @Scheduled(cron = "0 42 8 * * 0", zone = "Asia/Seoul") @@ -144,7 +151,7 @@ private void saveInfreanVideo(ArrayList infreanVideoDTOS, Techn public List findLectureListByPlatformNameAndTechStack( String platformName, String techStack) { - List videos = videoRepository.findByPlatformNameAndTeckStack(platformName, techStack).orElseThrow( + /* List videos = videoRepository.findByPlatformNameAndTeckStack(platformName, techStack).orElseThrow( ()->new RuntimeException("해당 플랫폼 및 기술 스택을 가진 영상이 존재하지 않습니다.") ); if(videos.isEmpty()){ @@ -152,24 +159,33 @@ public List findLectureListByPlatformNameAndTechStack( } videos.forEach(video-> videoRepository.save(video.setAddedCount())) - ; - - return videos.stream() + ;*/ + List videoList = queryRepository.findLectures(platformName, techStack); + addCountVideo(videoList); + return videoList.stream() .map(video -> new LectureResponseDTO(video.getId(), video.getUrl(), video.getTitle(), video.getThumnail_url(), video.getPrice(), video.getPlatformName())) .collect(Collectors.toList()); } + private void addCountVideo(List videoList) { + videoList.forEach(video-> + videoRepository.save(video.setAddedCount())); + } + + public Videos findById(Long id) { return videoRepository.findById(id) .orElseThrow(VideoNotFounException::new); } + @TimeTrace public List findTop3Videos(){ - List videos=videoRepository.findTop3ByOrderByCountDesc().orElseThrow( - () -> new RuntimeException("현재 video가 3개 미만입니다") - ); + List videos=videoRepository.findTop3ByOrderByCountDesc(); if(videos.isEmpty()){ throw new RuntimeException("현재 video가 3개 미만입니다"); } + for (Videos video : videos) { + System.out.println(video.getCount()); + } return videos.stream().map(video -> LectureResponseDTO.builder() .url(video.getUrl()) .title(video.getTitle()) diff --git a/dev-route/src/main/resources/application-dev.properties b/dev-route/src/main/resources/application-dev.properties index 9dd1a2e..8b7bb91 100644 --- a/dev-route/src/main/resources/application-dev.properties +++ b/dev-route/src/main/resources/application-dev.properties @@ -3,7 +3,8 @@ spring.application.name=dev-route spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/devroute?serverTimezone=Asia/Seoul spring.datasource.username=root -spring.datasource.password=1234 +spring.datasource.password=mhg1018! + spring.jpa.properties.hibernate.show_sql=false spring.jpa.properties.hibernate.format_sql=true diff --git a/dev-route/src/main/resources/application.properties b/dev-route/src/main/resources/application.properties index 8789d97..f1a787d 100644 --- a/dev-route/src/main/resources/application.properties +++ b/dev-route/src/main/resources/application.properties @@ -4,7 +4,7 @@ spring.profiles.active=dev crawling.link.jobplanet=https://www.jobplanet.co.kr/companies?industry_id=700&_rs_act=industries&_rs_con=gnb&_rs_element=category -#API URL +#API URLe spring.config.import=optional:application-secret.properties youtube.api.url.search=https://www.googleapis.com/youtube/v3/search?part=snippet&type=video udemy.api.url.search=https://www.udemy.com/api-2.0/courses/?search diff --git a/dev-route/src/test/java/com/teamdevroute/devroute/video/VideoServiceTest.java b/dev-route/src/test/java/com/teamdevroute/devroute/video/VideoServiceTest.java index c9d647f..6370685 100644 --- a/dev-route/src/test/java/com/teamdevroute/devroute/video/VideoServiceTest.java +++ b/dev-route/src/test/java/com/teamdevroute/devroute/video/VideoServiceTest.java @@ -13,6 +13,7 @@ import com.teamdevroute.devroute.video.fetcher.UdemyVideoFetcher; import com.teamdevroute.devroute.video.fetcher.YoutubeVideoFetcher; import com.teamdevroute.devroute.video.service.VideoService; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -20,6 +21,8 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.web.client.RestTemplate; import java.util.Collections; @@ -27,9 +30,12 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) +@SpringBootTest public class VideoServiceTest { @InjectMocks private VideoService videoService; + @Autowired + private VideoService videoServiceWired; @Mock private VideoRepository videoRepository; @Mock @@ -91,6 +97,13 @@ public void testFetchAndSaveUdemyVideosWithUrlIsNull() { //Tehcnology stack name이 총 9개임으로 9번 호출 되는 것이 맞음. verify(videoRepository, times(0)).save(any()); } + + + @DisplayName("조회수 상의 3개의 데이터를 조회한다.") + @Test + public void testTop3Video(){ + Assertions.assertNotNull(videoService.findTop3Videos()); + } //가짜 YoububeApiResponse를 가져온다. private YouTubeApiResponse getMockYouTubeApiResponse() { Item item = new Item();