package com.example.article;
import com.example.article.dto.CommentDto;
import com.example.article.entity.CommentEntity;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.server.ResponseStatusException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@Service
@RequiredArgsConstructor
public class CommentService {
private final ArticleRepository articleRepository;
private final CommentRepository commentRepository;
public CommentDto createComment(Long articleId, CommentDto dto) {
// articleId를 ID로 가진 ArticleEntity 가 존재 하는지?
if(!articleRepository.existsById(articleId))
throw new ResponseStatusException(HttpStatus.NOT_FOUND);
CommentEntity newComment = new CommentEntity();
newComment.setWriter(dto.getWriter());
newComment.setContent(dto.getContent());
newComment.setArticleId(articleId);
newComment = commentRepository.save(newComment);
return CommentDto.fromEntity(newComment);
}
// 게시글 댓글 전체 조회
public List<CommentDto> readCommentAll(Long articleId) {
List<CommentEntity> commentEntities = commentRepository.findAllByArticleId(articleId);
List<CommentDto> commentList = new ArrayList<>();
for (CommentEntity entity: commentEntities) {
commentList.add(CommentDto.fromEntity(entity));
}
return commentList;
}
// 게시글 댓글 수정
// 수정하고자 하는 댓글이 지정한 게시글에 있는지 확인할 목적으로 articleId도 첨부한다.
public CommentDto updateComment(Long articleId, Long commentId, CommentDto dto) {
// 요청한 댓글이 존재하는지
Optional<CommentEntity> optionalComment = commentRepository.findById(commentId);
// 존재하지 않으면 예외 발생
if (optionalComment.isEmpty()) throw new ResponseStatusException(HttpStatus.NOT_FOUND);
// 아니면 로직 진행
CommentEntity comment = optionalComment.get();
// 대상 댓글이 대상 게시글의 댓글이 맞는지
if (!articleId.equals(comment.getArticleId())) throw new ResponseStatusException(HttpStatus.BAD_REQUEST);
comment.setContent(dto.getContent());
comment.setWriter(dto.getWriter());
return CommentDto.fromEntity(commentRepository.save(comment));
}
// 게시글 댓글 삭제
public void deleteComment(Long articleId, Long commentId) {
Optional<CommentEntity> optionalComment = commentRepository.findById(commentId);
if (optionalComment.isEmpty()) throw new ResponseStatusException(HttpStatus.NOT_FOUND);
CommentEntity comment = optionalComment.get();
if (!articleId.equals(comment.getArticleId())) throw new ResponseStatusException(HttpStatus.BAD_REQUEST);
commentRepository.deleteById(commentId);
}
}
package com.example.article;
import com.example.article.dto.CommentDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Slf4j
@RestController
@RequestMapping("/articles/{articleId}/comments")
@RequiredArgsConstructor
public class CommentController {
private final CommentService service;
// POST /articles/{articleId}/comments
@PostMapping
public CommentDto create(
@PathVariable("articleId") Long articleId,
@RequestBody CommentDto dto
) {
return service.createComment(articleId, dto);
}
// 게시글 댓글 전체 조회
// GET /articles/{articleId}/comments
@GetMapping
public List<CommentDto> readAll(@PathVariable("articleId") Long articleId) {
return service.readCommentAll(articleId);
}
// 게시글 댓글 수정
// PUT /articles/{articleId}/comments/{commentId}
@PutMapping("/{commentId}")
public CommentDto update(
@PathVariable("articleId") Long articleId,
@PathVariable("commentId") Long commentId,
@RequestBody CommentDto dto
) {
return service.updateComment(articleId, commentId, dto);
}
// 게시글 댓글 삭제
// DELETE /articles/{articleId}/comments/{commentId}
@DeleteMapping("/{commentId}")
public void delete(
@PathVariable("articleId") Long articleId,
@PathVariable("commentId") Long commentId
) {
service.deleteComment(articleId, commentId);
}
}
package com.example.article.dto;
import com.example.article.entity.CommentEntity;
import lombok.Data;
@Data
public class CommentDto {
private Long id;
private Long articleId;
private String writer;
private String content;
public static CommentDto fromEntity(CommentEntity entity){
CommentDto dto = new CommentDto();
dto.setId(entity.getId());
dto.setArticleId(entity.getArticleId());
dto.setWriter(entity.getWriter());
dto.setContent(entity.getContent());
return dto;
}
}
package com.example.article.entity;
import jakarta.persistence.*;
import lombok.Data;
@Data
@Entity
@Table(name = "comments")
public class CommentEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long articleId;
private String writer;
private String content;
}
package com.example.article;
import com.example.article.entity.CommentEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface CommentRepository extends JpaRepository<CommentEntity, Long> {
// CommentEntity 중 articleId가 id인 CommentEntity 만 반환하는 메소드
List<CommentEntity> findAllByArticleId(Long id);
}
조회를 할 때, 어떠한 조건을 붙여서 특정한 자원을 조회하기 위한 방법 → 정렬, 필터링 등
경로 뒤에 입력 데이터를 함께 제공하는 형식
?
이후에 key=value
형태로 입력하며, 인자가 많은 경우 &
로 구분한다.
?
: 요구하는 자원에 대한 동적인 조건을 전달하는 용도로 사용한다. (페이지, 검색 등)
--1개의 데이터
/board?board_num=12
--다수의 데이터 &로 처리
/board?board_num=12&key=value
@Slf4j
@RestController
public class QueryController {
// GET /path?query=keyword&limit=20
@GetMapping("/path")
public Map<String, Object> queryParams(
@RequestParam(value = "query", defaultValue = "hello") String query,
@RequestParam(value = "limit", required = false) Integer limit
) {
log.info("query=" + query);
log.info("limit=" + limit);
Map<String, Object> response = new HashMap<>();
response.put("query",query);
response.put("limit", limit);
return response;
}
}
대량의 데이터를 여러 페이지로 나누는 기능이다.
public interface ArticleRepository extends JpaRepository<ArticleEntity, Long> {
// ID가 큰 순서대로 최상위 20개
List<ArticleEntity> findTop20ByOrderByIdDesc();
// ID가 특정 값보다 작은 데이터 중 큰 순서대로 최상위 20개
List<ArticleEntity> findTop20ByIdLessThanOrderByIdDesc(Long id);
}
public List<ArticleDto> readArticlePaged() {
List<ArticleDto> articleDtoList = new ArrayList<>();
for (ArticleEntity entity : repository.findTop20ByOrderByIdDesc()) {
articleDtoList.add(ArticleDto.fromEntity(entity));
}
return articleDtoList;
}
@GetMapping("/page-test")
public Page<ArticleEntity> readPageTest() {
return service.readArticlePaged();
}
100 ~ 81번 까지 20개의 article이 요청된다.
public Page<ArticleEntity> readArticlePaged() {
// PagingAndSortingRepository 메소드에 전달하는 용도
// 조회하고 싶은 페이지의 정보를 담는 객체
// 20개씩 페이지를 나눌때 0번 페이지를 달라고 요청하는 Pageable
Pageable pageable = PageRequest.of(0, 20);
Page<ArticleEntity> articleEntityPage = repository.findAll(pageable);
List<ArticleDto> articleDtoList = new ArrayList<>();
for (ArticleEntity entity : articleEntityPage) {
articleDtoList.add(ArticleDto.fromEntity(entity));
}
return articleEntityPage;
}
1 ~ 20까지의 정보가 표시되고, pageable에 여러 정보가 표시된다.
JPA의
PagingAndSortingRepository
인터페이스를 활용하면 repository를 건드릴 필요가 없다.
이를 사용하기 위해서는Pageable
객체가 필요하다.
PagingAndSortingRepository
메소드에 전달하기 위한 용도로 사용된다.
조회하고 싶은 페이지의 정보를 담는 객체라고 보면 된다.
특정 문자열이 제목에 포함되어 있는지를 기준으로 간단한 검색 기능을 구현
pageable
이용
public interface ArticleRepository
extends JpaRepository<ArticleEntity, Long> {
List<ArticleEntity> findTop20ByOrderByIdDesc();
List<ArticleEntity> findTop20ByIdLessThanOrderByIdDesc(Long id);
Page<ArticleEntity> findAllByTitleContains(String query, Pageable pageable);
}
public Page<ArticleDto> search(
String query,
Integer pageNumber
) {
Pageable pageable = PageRequest.of(
pageNumber,
20,
Sort.by("id").descending());
return repository.findAllByTitleContains(query, pageable)
.map(ArticleDto::fromEntity);
}
@GetMapping("/search")
public Page<ArticleDto> search(
@RequestParam("query") String query,
@RequestParam(value = "page", defaultValue = "0")
Integer pageNumber
) {
return service.search(query, pageNumber);
}
출처 : 멋사 5기 백엔드 위키 7팀 7번방의 회고
https://school.programmers.co.kr/learn/courses/30/lessons/120899
class Solution {
public int[] solution(int[] array) {
int[] answer = new int[2];
for (int i = 0; i < array.length; i++) {
if(answer[0] < array[i]) {
answer[0] = array[i];
answer[1] = i;
}
}
return answer;
}
}
https://school.programmers.co.kr/learn/courses/30/lessons/181884
class Solution {
public int solution(int[] numbers, int n) {
int i = 0;
int sum = 0;
while (sum <= n) sum += numbers[i++];
return sum;
}
}
https://school.programmers.co.kr/learn/courses/30/lessons/70128
class Solution {
public int solution(int[] a, int[] b) {
int sum = 0;
for (int i = 0; i < a.length; i++) sum += a[i] * b[i];
return sum;
}
}
easy
오전에 배운 이진 탐색 트리는 탐색과 삽입까지 코드를 작성했는데 아마 내일 삭제까지 구현할 것 같아서 작성하지 않았다. 결론은 그냥 어렵다.
오후 스프링 시간은 실로 유구무언. 잘되던 실습이 map 부분에서 막혀서 던지려다가 search 기능은 구현했다. 구현하건 말건 오늘이 위키날이 아님에 다시 한 번 감사할 뿐이다. 컨디션은 나쁘지 않았는데 그냥 내용 자체가 들어오질 않았다. 이거 이러다가 블로그 전체 리뷰가 이해 안된다로 도배가 될 것 같은데 ㅎ
알고리즘은 태환님이 매번 풀만한 난이도로 내주셔서 좋다. 조만간 레벨 1로 올리신다는데 정렬함수도 모르는 내겐 이제 뭐 알고리즘 하차 예고 소식과 다름 없는 것 같다. 이거나 저거나 요즘 아주 멘탈 256등분이다.
Really great information. This is my first time coming into geometry dash lite contact with these specialized terms. Looking forward to more advanced knowledge.