[Practice] 사용자 API 만들기 (5)

2021. 4. 13. 01:38Spring/Practice

1. 문제

  • 내가 작성한 공지사항 목록에 대한 API 작성
  • 삭제일과 삭제자 아이디는 보안상 반환하지 않음
  • 작성자 정보를 모두 내리지 않고 작성자의 아이디와 이름만 반환

 

 

 

2. 풀이

- schema.sql

DROP TABLE IF EXISTS NOTICE;

create table USER (
    ID          BIGINT auto_increment primary key,
    EMAIL       VARCHAR(255),
    USER_NAME   VARCHAR(255),
    PASSWORD    VARCHAR(255),
    PHONE       VARCHAR(255),
    REG_DATE    TIMESTAMP,
    UPDATE_DATE TIMESTAMP
)

create table NOTICE (
    ID          BIGINT auto_increment primary key,
    TITLE       VARCHAR(255),
    CONTENTS    VARCHAR(255),

    HITS        INTEGER,
    LIKES       INTEGER,

    REG_DATE    TIMESTAMP,
    UPDATE_DATE TIMESTAMP,
    DELETED     BOOLEAN DEFAULT FALSE,
    DELETED_DATE    TIMESTAMP,

    USER_ID     BIGINT,
    constraint FK_NOTICE_USER_ID foreign key(USER_ID) references USER(ID)
)

- data.sql

INSERT INTO USER(ID, EMAIL, PASSWORD, PHONE, REG_DATE, UPDATE_DATE, USER_NAME) VALUES(1, 'test1@naver.com', '1111', '010-1111-1111', '2021-01-01 01:01:01.000000', null, '테스트1');
INSERT INTO USER(ID, EMAIL, PASSWORD, PHONE, REG_DATE, UPDATE_DATE, USER_NAME) VALUES(2, 'test2@naver.com', '2222', '010-2222-2222', '2021-01-02 02:02:02.000000', null, '테스트2');
INSERT INTO USER(ID, EMAIL, PASSWORD, PHONE, REG_DATE, UPDATE_DATE, USER_NAME) VALUES(3, 'test3@naver.com', '3333', '010-3333-3333', '2021-01-03 03:03:03.000000', null, '테스트3');

INSERT INTO NOTICE(ID, CONTENTS, HITS, LIKES, REG_DATE, TITLE, USER_ID) VALUES(1, '내용1', 0, 0, '2021-01-01 01:01:01.000000', '제목1', 1);
INSERT INTO NOTICE(ID, CONTENTS, HITS, LIKES, REG_DATE, TITLE, USER_ID) VALUES(2, '내용2', 0, 0, '2021-01-02 02:02:02.000000', '제목2', 1);
INSERT INTO NOTICE(ID, CONTENTS, HITS, LIKES, REG_DATE, TITLE, USER_ID) VALUES(3, '내용3', 0, 0, '2021-01-03 03:03:03.000000', '제목3', 1);

- Notice.java

package com.example.jpa.sample.notice.entity;

import com.example.jpa.sample.user.entity.User;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.*;
import java.time.LocalDateTime;

@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
@Data
public class Notice {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne // 사용자는 여러 글을 작성할 수 있음
    @JoinColumn
    private User user;

    @Column
    private String title;

    @Column
    private String contents;

    @Column
    private LocalDateTime regDate;

    @Column
    private LocalDateTime updateDate; // 수정일

    @Column
    private int hits;

    @Column
    private int likes;

    @Column
    private boolean deleted; // 삭제 여부

    @Column
    private LocalDateTime deletedDate; // 삭제일
}

- NoticeRepository.java

package com.example.jpa.sample.notice.repository;

import com.example.jpa.sample.notice.entity.Notice;
import com.example.jpa.sample.user.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

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

@Repository
public interface NoticeRepository extends JpaRepository<Notice, Long> {


    Optional<List<Notice>> findByIdIn(List<Long> idList);

    Optional<List<Notice>> findByTitleAndContentsAndRegDateIsGreaterThanEqual(String title, String contents, LocalDateTime regDate);

    int countByTitleAndContentsAndRegDateIsGreaterThanEqual(String title, String contents, LocalDateTime regDate);

    List<Notice> findByUser(User user);
}

- NoticeResponse.java

package com.example.jpa.sample.notice.model;

import com.example.jpa.sample.notice.entity.Notice;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public class NoticeResponse {

    private Long id;

    private Long regUserId;
    private String regName;

    private String title;
    private String contents;
    private LocalDateTime regDate;
    private LocalDateTime updateDate;
    private int hits;
    private int likes;

    public static NoticeResponse of(Notice notice) {

        return NoticeResponse.builder()
                .id(notice.getId())
                .regUserId(notice.getUser().getId())
                .regName(notice.getUser().getName())
                .title(notice.getTitle())
                .contents(notice.getContents())
                .regDate(notice.getRegDate())
                .updateDate(notice.getUpdateDate())
                .hits(notice.getHits())
                .likes(notice.getLikes())
                .build();
    }
}

- ApiUserController.java

package com.example.jpa.sample.user.controller;

import com.example.jpa.sample.notice.entity.Notice;
import com.example.jpa.sample.notice.model.ResponseError;
import com.example.jpa.sample.notice.repository.NoticeRepository;
import com.example.jpa.sample.user.entity.User;
import com.example.jpa.sample.user.exception.UserNotFoundException;
import com.example.jpa.sample.user.model.UserInput;
import com.example.jpa.sample.user.model.UserResponse;
import com.example.jpa.sample.user.model.UserUpdate;
import com.example.jpa.sample.user.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@RequiredArgsConstructor
@RestController
public class ApiUserController {

    private final UserRepository userRepository;
    private final NoticeRepository noticeRepository;

    /*
    // 문제 1
    @PostMapping("/api/user")
    public ResponseEntity<?> addUser(@RequestBody @Valid UserInput userInput, Errors errors) {

        List<ResponseError> responseErrorList = new ArrayList<>();

        if(errors.hasErrors()) {
            errors.getAllErrors().forEach(e -> {
                responseErrorList.add(ResponseError.of((FieldError)e));
            });
            return new ResponseEntity<>(responseErrorList, HttpStatus.BAD_REQUEST);
        }

//        return ResponseEntity.ok().build();
        return new ResponseEntity<>(HttpStatus.OK);
    }
     */

    // 문제 2
    @PostMapping("/api/user")
    public ResponseEntity<?> addUser(@RequestBody @Valid UserInput userInput, Errors errors) {

        List<ResponseError> responseErrorList = new ArrayList<>();

        if(errors.hasErrors()) {
            errors.getAllErrors().forEach(e -> {
                responseErrorList.add(ResponseError.of((FieldError)e));
            });
            return new ResponseEntity<>(responseErrorList, HttpStatus.BAD_REQUEST);
        }

        userRepository.save(User.builder()
                .email(userInput.getEmail())
                .name(userInput.getName())
                .password(userInput.getPassword())
                .phone(userInput.getPhone())
                .regDate(LocalDateTime.now())
                .build()
        );

        return new ResponseEntity<>(HttpStatus.OK);
    }

    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<?> handlerUserNotFoundException(UserNotFoundException exception) {
        return new ResponseEntity<>(exception.getMessage(), HttpStatus.BAD_REQUEST);
    }

    // 문제 3
    @PutMapping("/api/user/{id}")
    public ResponseEntity<?> updateUser(@PathVariable Long id, @RequestBody @Valid UserUpdate userUpdate, Errors errors) {

        List<ResponseError> responseErrorList = new ArrayList<>();

        if(errors.hasErrors()) {
            errors.getAllErrors().forEach(e -> {
                responseErrorList.add(ResponseError.of((FieldError)e));
            });
            return new ResponseEntity<>(responseErrorList, HttpStatus.BAD_REQUEST);
        }

        User user = userRepository.findById(id).orElseThrow(() -> new UserNotFoundException("사용자 정보가 없습니다."));
        user.setPhone(userUpdate.getPhone());
        user.setUpdateDate(LocalDateTime.now());
        userRepository.save(user);

        return ResponseEntity.ok().build();
    }

    // 문제 4
    @GetMapping("/api/user/{id}")
    public UserResponse getUser(@PathVariable Long id) {

        User user = userRepository.findById(id).orElseThrow(() -> new UserNotFoundException("사용자 정보가 없습니다."));

//        UserResponse userResponse = new UserResponse(user);
        UserResponse userResponse = UserResponse.of(user);

        return userResponse;
    }

    // 문제 5
    @GetMapping("/api/user/{id}/notice")
    public List<Notice> userNotice(@PathVariable Long id) {

        User user = userRepository.findById(id).orElseThrow(() -> new UserNotFoundException("사용자 정보가 없습니다."));

        List<Notice> noticeList = noticeRepository.findByUser(user);
        return noticeList;
    }
}

728x90