diff --git a/src/main/java/com/yam/app/account/infrastructure/WebConfiguration.java b/src/main/java/com/yam/app/account/infrastructure/WebConfiguration.java index c553a50..3ec3545 100644 --- a/src/main/java/com/yam/app/account/infrastructure/WebConfiguration.java +++ b/src/main/java/com/yam/app/account/infrastructure/WebConfiguration.java @@ -12,7 +12,8 @@ public class WebConfiguration implements WebMvcConfigurer { private static final String[] EXCLUDE_PATHS = { "/api/accounts/login", "/api/accounts/authorize", - "/api/accounts" + "/api/accounts", + "/api/articles/all" }; @Override diff --git a/src/main/java/com/yam/app/article/application/ArticleFacade.java b/src/main/java/com/yam/app/article/application/ArticleFacade.java index c078fd3..8416e32 100644 --- a/src/main/java/com/yam/app/article/application/ArticleFacade.java +++ b/src/main/java/com/yam/app/article/application/ArticleFacade.java @@ -1,7 +1,11 @@ package com.yam.app.article.application; +import com.yam.app.article.domain.ArticleReader; import com.yam.app.article.domain.WriteArticleProcessor; +import com.yam.app.article.presentation.ArticlePreviewResponse; import com.yam.app.article.presentation.WriteArticleCommand; +import java.util.List; +import java.util.stream.Collectors; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -9,9 +13,12 @@ import org.springframework.transaction.annotation.Transactional; public class ArticleFacade { private final WriteArticleProcessor writeArticleProcessor; + private final ArticleReader articleReader; - public ArticleFacade(WriteArticleProcessor writeArticleProcessor) { + public ArticleFacade(WriteArticleProcessor writeArticleProcessor, + ArticleReader articleReader) { this.writeArticleProcessor = writeArticleProcessor; + this.articleReader = articleReader; } @Transactional @@ -20,4 +27,15 @@ public class ArticleFacade { command.getTitle(), command.getContent(), command.getImage(), command.getTags()); } + + @Transactional(readOnly = true) + public List findAll(int offset, int limit) { + var idx = articleReader.findAll(); + return articleReader.findAllById(offset, limit, idx) + .stream() + .map(dto -> new ArticlePreviewResponse(dto.getId(), dto.getAuthorId(), dto.getTitle(), + dto.getNickname(), dto.getImage(), dto.getCreatedAt(), dto.getModifiedAt(), + dto.getStatus()) + ).collect(Collectors.toList()); + } } diff --git a/src/main/java/com/yam/app/article/domain/ArticleDto.java b/src/main/java/com/yam/app/article/domain/ArticleDto.java new file mode 100644 index 0000000..4dffdd1 --- /dev/null +++ b/src/main/java/com/yam/app/article/domain/ArticleDto.java @@ -0,0 +1,17 @@ +package com.yam.app.article.domain; + +import java.time.LocalDateTime; +import lombok.Data; + +@Data +public final class ArticleDto { + + private Long id; + private Long authorId; + private String title; + private String status; + private LocalDateTime createdAt; + private LocalDateTime modifiedAt; + private String nickname; + private String image; +} diff --git a/src/main/java/com/yam/app/article/domain/ArticleReader.java b/src/main/java/com/yam/app/article/domain/ArticleReader.java index 98a6879..72a7cb5 100644 --- a/src/main/java/com/yam/app/article/domain/ArticleReader.java +++ b/src/main/java/com/yam/app/article/domain/ArticleReader.java @@ -12,5 +12,8 @@ public interface ArticleReader { boolean existsById(Long articleId); - List findAll(@Param("offset") int offset, @Param("limit") int limit); + List findAll(); + + List findAllById(@Param("offset") int offset, + @Param("limit") int limit, @Param("idx") List idx); } diff --git a/src/main/java/com/yam/app/article/infrastructure/MybatisArticleRepository.java b/src/main/java/com/yam/app/article/infrastructure/MybatisArticleRepository.java index bd4569b..c327b9f 100644 --- a/src/main/java/com/yam/app/article/infrastructure/MybatisArticleRepository.java +++ b/src/main/java/com/yam/app/article/infrastructure/MybatisArticleRepository.java @@ -1,6 +1,7 @@ package com.yam.app.article.infrastructure; import com.yam.app.article.domain.Article; +import com.yam.app.article.domain.ArticleDto; import com.yam.app.article.domain.ArticleReader; import com.yam.app.article.domain.ArticleRepository; import java.util.List; @@ -42,8 +43,13 @@ public final class MybatisArticleRepository implements ArticleReader, ArticleRep } @Override - public List findAll(int offset, int limit) { - return template.getMapper(ArticleReader.class).findAll(offset, limit); + public List findAll() { + return template.getMapper(ArticleReader.class).findAll(); + } + + @Override + public List findAllById(int offset, int limit, List idx) { + return template.getMapper(ArticleReader.class).findAllById(offset, limit, idx); } } diff --git a/src/main/java/com/yam/app/article/presentation/ArticlePreviewResponse.java b/src/main/java/com/yam/app/article/presentation/ArticlePreviewResponse.java new file mode 100644 index 0000000..ca9c2bb --- /dev/null +++ b/src/main/java/com/yam/app/article/presentation/ArticlePreviewResponse.java @@ -0,0 +1,30 @@ +package com.yam.app.article.presentation; + +import java.time.LocalDateTime; +import lombok.Getter; + +@Getter +public final class ArticlePreviewResponse { + + private final Long id; + private final Long authorId; + private final String title; + private final String nickname; + private final String memberImage; + private final LocalDateTime createdAt; + private final LocalDateTime modifiedAt; + private final String status; + + public ArticlePreviewResponse(Long id, Long authorId, String title, + String nickname, String memberImage, LocalDateTime createdAt, + LocalDateTime modifiedAt, String status) { + this.id = id; + this.authorId = authorId; + this.title = title; + this.nickname = nickname; + this.memberImage = memberImage; + this.createdAt = createdAt; + this.modifiedAt = modifiedAt; + this.status = status; + } +} diff --git a/src/main/java/com/yam/app/article/presentation/ArticleQueryApi.java b/src/main/java/com/yam/app/article/presentation/ArticleQueryApi.java new file mode 100644 index 0000000..789730a --- /dev/null +++ b/src/main/java/com/yam/app/article/presentation/ArticleQueryApi.java @@ -0,0 +1,32 @@ +package com.yam.app.article.presentation; + +import com.yam.app.article.application.ArticleFacade; +import com.yam.app.common.ApiResult; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +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; + +@RestController +@RequestMapping( + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE +) +public final class ArticleQueryApi { + + private final ArticleFacade articleFacade; + + public ArticleQueryApi(ArticleFacade articleFacade) { + this.articleFacade = articleFacade; + } + + @GetMapping("/api/articles/all") + public ResponseEntity findAll( + @RequestParam(value = "offset", defaultValue = "0") int offset, + @RequestParam(value = "limit", defaultValue = "20") int limit) { + return ResponseEntity.ok( + ApiResult.success(articleFacade.findAll(offset, limit))); + } +} diff --git a/src/main/resources/mapper/xml/ArticleQueryMapper.xml b/src/main/resources/mapper/xml/ArticleQueryMapper.xml index 3008999..acbba78 100644 --- a/src/main/resources/mapper/xml/ArticleQueryMapper.xml +++ b/src/main/resources/mapper/xml/ArticleQueryMapper.xml @@ -7,16 +7,43 @@ SELECT DISTINCT(a.id) AS article_id, a.created_at FROM article a - INNER JOIN article_tag atg ON atg.article_id = a.id - INNER JOIN tag t ON t.id = atg.tag_id - ORDER BY a.created_at DESC - LIMIT #{offset}, #{limit} + LEFT OUTER JOIN article_tag atg ON atg.article_id = a.id + LEFT OUTER JOIN tag t ON t.id = atg.tag_id + + + + + + + + + + + + +