Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4주차-과제/정답 #17

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
@@ -0,0 +1,51 @@
package com.example.urlshortener.domain.url.controller;

import com.example.urlshortener.common.dto.Response;
import com.example.urlshortener.domain.url.dto.ShortenedUrlDto;
import com.example.urlshortener.domain.url.service.UrlService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotBlank;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RequiredArgsConstructor
@RestController
@RequestMapping("/short-links/list")
@Tag(name = "🍃 4주차 과제", description = "4주차 과제입니다.")
public class Week4Controller {

private final UrlService urlService;

@Operation(
summary = "Data JPA로 URL 조회하기",
responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "500", description = "INTERNAL_SERVER_ERROR")
}
)
@GetMapping("/jpa")
public Response<List<ShortenedUrlDto>> getShortUrlsWithJpa(@NotBlank @RequestParam("inquiry") String inquiry) {
List<ShortenedUrlDto> shortenedUrls = urlService.getShortUrlsWithJpa(inquiry);
return Response.data(shortenedUrls);
}

@Operation(
summary = "QueryDsl로 URL 조회하기",
responses = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "500", description = "INTERNAL_SERVER_ERROR")
}
)
@GetMapping("/query-dsl")
public Response<List<ShortenedUrlDto>> getShortUrl(@NotBlank @RequestParam("inquiry") String inquiry) {
List<ShortenedUrlDto> shortenedUrls = urlService.getShortUrlsWithQueryDsl(inquiry);
return Response.data(shortenedUrls);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import lombok.Getter;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Getter
@AllArgsConstructor
Expand All @@ -25,4 +27,10 @@ public static ShortenedUrlDto from(ShortenedUrl shortenedUrl) {
.createdAt(shortenedUrl.getCreatedAt())
.build();
}

public static List<ShortenedUrlDto> from(List<ShortenedUrl> shortenedUrls) {
return shortenedUrls.stream()
.map(ShortenedUrlDto::from)
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.example.urlshortener.domain.url.repository;

import com.example.urlshortener.domain.url.dto.ShortenedUrlDto;
import com.example.urlshortener.domain.url.entity.QShortenedUrl;
import com.example.urlshortener.domain.url.entity.ShortenedUrl;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

물어봤던 질문: Service 어노테이션이 들어온건 어떤 관점의 차이가 있어서인걸까요??

@RequiredArgsConstructor
public class ShortenedUrlQueryRepository {
private final JPAQueryFactory jpaQueryFactory;

public List<ShortenedUrlDto> getShortUrlsWithQueryDsl(String inquiry) {
QShortenedUrl shortenedUrl = QShortenedUrl.shortenedUrl;
List<ShortenedUrl> shortenedUrls = jpaQueryFactory
.selectFrom(shortenedUrl)
.where(shortenedUrl.originUrl.contains(inquiry))
.fetch();

return ShortenedUrlDto.from(shortenedUrls);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;

@Repository
Expand All @@ -36,4 +37,6 @@ public interface ShortenedUrlRepository extends JpaRepository<ShortenedUrl, Long
int updateOriginUrlByShortUrl(@Param("originUrl") String originUrl, @Param("shortUrl") String shortUrl);

Iterable<ShortUrlOnly> findShortenedUrlByOriginUrl(String originUrl);

List<ShortenedUrl> findAllByOriginUrlContains(String inquiry);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,20 @@
import com.example.urlshortener.domain.url.dto.ShortenedUrlDto;
import com.example.urlshortener.domain.url.entity.ShortenedUrl;
import com.example.urlshortener.domain.url.exception.UrlNotFoundException;
import com.example.urlshortener.domain.url.repository.ShortenedUrlQueryRepository;
import com.example.urlshortener.domain.url.repository.ShortenedUrlRepository;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

@Service
@RequiredArgsConstructor
public class UrlService {
private final ShortenedUrlRepository shortenedUrlRepository;
private final ShortenedUrlQueryRepository shortenedUrlQueryRepository;

@Transactional
public ShortenedUrlDto createShortUrl(String url) {
Expand Down Expand Up @@ -45,4 +48,14 @@ public String getOriginUrl(String shortId) {

return shortenedUrl.getOriginUrl();
}

public List<ShortenedUrlDto> getShortUrlsWithJpa(String inquiry) {
List<ShortenedUrl> shortenedUrls = shortenedUrlRepository.findAllByOriginUrlContains(inquiry);

return ShortenedUrlDto.from(shortenedUrls);
}

public List<ShortenedUrlDto> getShortUrlsWithQueryDsl(String inquiry) {
return shortenedUrlQueryRepository.getShortUrlsWithQueryDsl(inquiry);
}
}
12 changes: 6 additions & 6 deletions src/main/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,19 @@ spring:
jpa:
database-platform: org.hibernate.dialect.H2Dialect
hibernate:
ddl-auto: create # (none, create, create-drop, update, validate)
ddl-auto: none # (none, create, create-drop, update, validate)
properties:
hibernate:
dialect: org.hibernate.dialect.H2Dialect # Dialect: 데이터베이스에 대한 특정 SQL 문법과 데이터 타입 매핑에 대한 규칙을 제공
format_sql: true # SQL 쿼리를 포맷팅하여 출력할지 여부 설정
show_sql: true # SQL 쿼리를 출력할지 여부 설정

# TODO: 발표 후 ddl-auto: create 로 변경하기(보통 ddl-auto로 사용함)
# sql:
# init:
# mode: always # ddl-auto: none, H2는 필요없음(어차피 사라지기 때문)
# schema-locations: classpath:db-init-scripts/schema.sql
# data-locations: classpath:db-init-scripts/data.sql
sql:
init:
mode: always # ddl-auto: none, H2는 필요없음(어차피 사라지기 때문)
schema-locations: classpath:db-init-scripts/schema.sql
data-locations: classpath:db-init-scripts/data.sql

#logging:
# pattern:
Expand Down
10 changes: 5 additions & 5 deletions src/main/resources/db-init-scripts/data.sql
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
INSERT INTO shortened_url (short_url, origin_url, created_at) VALUES
('http://short.url/abc', 'http://example.com/page1', '2024-04-01 10:00:00'),
('http://short.url/def', 'http://example.com/page2', '2024-04-02 12:00:00'),
('http://short.url/ghi', 'http://example.com/page3', '2024-04-03 14:00:00'),
('http://short.url/jkl', 'http://example.com/page4', '2024-04-04 16:00:00'),
('http://short.url/mno', 'http://example.com/page5', '2024-04-05 18:00:00');
('abc', 'http://example.com/page1', '2024-04-01 10:00:00'),
('def', 'http://example.com/page2', '2024-04-02 12:00:00'),
('ghi', 'http://example.com/page3', '2024-04-03 14:00:00'),
('jkl', 'http://example.com/page4', '2024-04-04 16:00:00'),
('mno', 'http://example.com/page5', '2024-04-05 18:00:00');
6 changes: 3 additions & 3 deletions src/test/java/com/example/urlshortener/ch3/Ch3Test3.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class Ch3Test3 {

@Test
public void givenCreateShortenedUrlWhenLoadTheShortenedUrlThenExpectSameShortenedUrl() {
ShortenedUrl shortenedUrl = new ShortenedUrl("http://short.url/abc", "http://example.com/page1", LocalDateTime.now());
ShortenedUrl shortenedUrl = new ShortenedUrl("abc", "http://example.com/page1", LocalDateTime.now());
ShortenedUrl savedShortenedUrl = shortenedUrlRepository.save(shortenedUrl);

// TODO: 실제로는 이렇게 사용하면 안됨 with Transactional
Expand All @@ -28,7 +28,7 @@ public void givenCreateShortenedUrlWhenLoadTheShortenedUrlThenExpectSameShortene

@Test
public void givenUpdateShortenedUrlWhenLoadTheShortenedUrlThenExpectUpdatedShortenedUrl() {
ShortenedUrl shortenedUrl = new ShortenedUrl("http://short.url/abc", "http://example.com/page1", LocalDateTime.now());
ShortenedUrl shortenedUrl = new ShortenedUrl("abc", "http://example.com/page1", LocalDateTime.now());
shortenedUrlRepository.save(shortenedUrl);

shortenedUrl.setOriginUrl("http://example.com/page2");
Expand All @@ -40,7 +40,7 @@ public void givenUpdateShortenedUrlWhenLoadTheShortenedUrlThenExpectUpdatedShort

@Test
public void givenDeleteShortenedUrlWhenLoadTheShortenedUrlThenExpectNoShortenedUrl() {
ShortenedUrl shortenedUrl = new ShortenedUrl("http://short.url/abc", "http://example.com/page1", LocalDateTime.now());
ShortenedUrl shortenedUrl = new ShortenedUrl("abc", "http://example.com/page1", LocalDateTime.now());
ShortenedUrl savedShortenedUrl = shortenedUrlRepository.save(shortenedUrl);

assertThat(shortenedUrlRepository.findById(savedShortenedUrl.getId()).get().getId()).isEqualTo(savedShortenedUrl.getId());
Expand Down
14 changes: 7 additions & 7 deletions src/test/java/com/example/urlshortener/ch3/Ch3Test4.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class Ch3Test4 {

@Test
public void givenCreateShortenedUrlWhenLoadTheShortenedUrlThenExpectSameShortenedUrl() {
ShortenedUrl shortenedUrl = new ShortenedUrl("http://short.url/abc", "http://example.com/page1", LocalDateTime.now());
ShortenedUrl shortenedUrl = new ShortenedUrl("abc", "http://example.com/page1", LocalDateTime.now());
ShortenedUrl savedShortenedUrl = shortenedUrlRepository.save(shortenedUrl);

assertThat(shortenedUrlRepository.findByOriginUrl(savedShortenedUrl.getOriginUrl()).get().getId()).isEqualTo(savedShortenedUrl.getId());
Expand All @@ -41,7 +41,7 @@ public void givenDataAvailableWhenSortsFirstPageThenGetSortedData() {
Condition<ShortenedUrl> sortedFirstCourseCondition = new Condition<ShortenedUrl>() {
@Override
public boolean matches(ShortenedUrl shortenedUrl) {
return shortenedUrl.getId() == 5L && shortenedUrl.getShortUrl().equals("http://short.url/mno");
return shortenedUrl.getId() == 5L && shortenedUrl.getShortUrl().equals("mno");
}
};

Expand All @@ -51,11 +51,11 @@ public boolean matches(ShortenedUrl shortenedUrl) {

private void saveMockedShortenedUrls() {
List<ShortenedUrl> shortenedUrls = List.of(
new ShortenedUrl("http://short.url/abc", "http://example.com/page1", LocalDateTime.parse("2024-04-01T10:00:00")),
new ShortenedUrl("http://short.url/def", "http://example.com/page2", LocalDateTime.parse("2024-04-02T12:00:00")),
new ShortenedUrl("http://short.url/ghi", "http://example.com/page3", LocalDateTime.parse("2024-04-03T14:00:00")),
new ShortenedUrl("http://short.url/jkl", "http://example.com/page4", LocalDateTime.parse("2024-04-04T16:00:00")),
new ShortenedUrl("http://short.url/mno", "http://example.com/page5", LocalDateTime.parse("2024-04-05T18:00:00"))
new ShortenedUrl("abc", "http://example.com/page1", LocalDateTime.parse("2024-04-01T10:00:00")),
new ShortenedUrl("def", "http://example.com/page2", LocalDateTime.parse("2024-04-02T12:00:00")),
new ShortenedUrl("ghi", "http://example.com/page3", LocalDateTime.parse("2024-04-03T14:00:00")),
new ShortenedUrl("jkl", "http://example.com/page4", LocalDateTime.parse("2024-04-04T16:00:00")),
new ShortenedUrl("mno", "http://example.com/page5", LocalDateTime.parse("2024-04-05T18:00:00"))
);

shortenedUrlRepository.saveAll(shortenedUrls);
Expand Down
2 changes: 1 addition & 1 deletion src/test/java/com/example/urlshortener/ch3/Ch3Test5.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class Ch3Test5 {

@Test
public void givenShortenedUrlsWhenLoadShortenedUrlsWithQueryThenExpectCorrectShortenedUrlsDetails() {
ShortenedUrl shortenedUrl = new ShortenedUrl("http://short.url/abc", "http://example.com/page1", LocalDateTime.now());
ShortenedUrl shortenedUrl = new ShortenedUrl("abc", "http://example.com/page1", LocalDateTime.now());
ShortenedUrl savedShortenedUrl = shortenedUrlRepository.save(shortenedUrl);

assertThat(shortenedUrlRepository.findByShortUrlWithQuery(savedShortenedUrl.getShortUrl()).get().getOriginUrl()).isEqualTo("http://example.com/page1");
Expand Down
12 changes: 6 additions & 6 deletions src/test/java/com/example/urlshortener/ch3/Ch3Test7.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,16 @@ public void givenAShortenedUrlAvailableWhenGetShortenedUrlByNameThenGetShortened

Iterable<ShortUrlOnly> result = shortenedUrlRepository.findShortenedUrlByOriginUrl("http://example.com/page1");

assertThat(result).extracting("shortUrl").contains("http://short.url/abc");
assertThat(result).extracting("shortUrl").contains("abc");
}

private void saveMockedShortenedUrls() {
List<ShortenedUrl> shortenedUrls = List.of(
new ShortenedUrl("http://short.url/abc", "http://example.com/page1", LocalDateTime.parse("2024-04-01T10:00:00")),
new ShortenedUrl("http://short.url/def", "http://example.com/page2", LocalDateTime.parse("2024-04-02T12:00:00")),
new ShortenedUrl("http://short.url/ghi", "http://example.com/page3", LocalDateTime.parse("2024-04-03T14:00:00")),
new ShortenedUrl("http://short.url/jkl", "http://example.com/page4", LocalDateTime.parse("2024-04-04T16:00:00")),
new ShortenedUrl("http://short.url/mno", "http://example.com/page5", LocalDateTime.parse("2024-04-05T18:00:00"))
new ShortenedUrl("abc", "http://example.com/page1", LocalDateTime.parse("2024-04-01T10:00:00")),
new ShortenedUrl("def", "http://example.com/page2", LocalDateTime.parse("2024-04-02T12:00:00")),
new ShortenedUrl("ghi", "http://example.com/page3", LocalDateTime.parse("2024-04-03T14:00:00")),
new ShortenedUrl("jkl", "http://example.com/page4", LocalDateTime.parse("2024-04-04T16:00:00")),
new ShortenedUrl("mno", "http://example.com/page5", LocalDateTime.parse("2024-04-05T18:00:00"))
);

shortenedUrlRepository.saveAll(shortenedUrls);
Expand Down