20220602_Spring_MemoAPI만들기

Today Jeeho Learned·2022년 6월 2일
0

Spring

목록 보기
5/31
post-thumbnail

3주차 CRUD가 가능한 메모장을 만들어보자

Repository를 만들기

  • domain패키지를 만들고 시작하는데, entity 즉 테이블과 연결되는 클래스와 Repository는 domain 패키지 안에서 만들어줘야한다.
    (- domain 패키지 안에는 Memo클래스, Timestamped클래스, MemoRepository, dto)
package com.sparta.week03.domain;

import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@NoArgsConstructor // 기본생성자를 만듭니다.
@Getter
@Entity // 테이블과 연계됨을 스프링에게 알려줍니다.

public class Memo extends Timestamped { // 생성,수정 시간을 자동으로 만들어줍니다.
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Id
    private Long id;

    @Column(nullable = false)
    private String username;

    @Column(nullable = false)
    private String contents;

    public Memo(String username, String contents) {
        this.username = username;
        this.contents = contents;
    }

    public Memo(MemoRequestDto requestDto) {
        this.username = requestDto.getUsername();
        this.contents = requestDto.getContents();
    }
}

= Memo클래스이다. @들어가는 어노테이션들을 주의깊게보고, 실제 프로젝트에 사용해보자

  • Timestamped 클래스를 따로 만들어주자

package com.sparta.week03.domain;

import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;

@MappedSuperclass // Entity가 자동으로 컬럼으로 인식합니다.
@EntityListeners(AuditingEntityListener.class) // 생성/변경 시간을 자동으로 업데이트합니다.
public abstract class Timestamped { //abstract를 사용하면서 상속을 통해서만 사용할수있는 클래스다.

    @CreatedDate //생성시간을 나타냄
    private LocalDateTime createdAt;

    @LastModifiedDate //수정시간을 나타냄
    private LocalDateTime modifiedAt;
}

특별하게 추상클래스로 만들어줬는데, 상속을 통해서만 사용이 가능하도록 만들어주었다.
새로운@ 어노테이션들이 많이있다. 주석 달린것들을 토대로 이해해보자.

  • MemoRepository를 생성하자! 단 class가 아니라 interface로 만들어줘야한다.
    인터페이스는 ? : 클래스에서 멤버변수가 없고 메소드만 있는 것들.

MemoRepository에서 JpaRepository의 메소드들을(findAll, delete, findById, save등등)을 사용할 것이라고 알려주는 것이고, 그 대상을 어디에 가져가 쓸것이냐에 대해서도 Memo라는 클래스고 Long이라는 id에 쓸것이라는 것도 알려준다.

단 여기서 List Memo findAllByOrderByModifiedAtDesc(); 요녀석은 뭘까 ?
JPA공식 사이트를 들어가보자. JPA규칙대로 메소드명만 잘 만들어주면 알아서 그 뒤의 로직을 다 만들어 준다.
findAll / By / OrderBy / ModifiedAt DESC 로 나눠서 볼수있는데
= 다 찾고 순서대로 정렬해줘라, 최신 수정된 날짜를 기준으로 ! 라는 뜻이다.

  • MemoRequestDto를 생성해보자.
    역시 Domain안에다가 생성해줘야한다. 알지? requestDto는 필요한 정보를 물고 다니는 녀셕인데, 여기서 무언가를 수정해주려면 기본적으로 2개(유저이름,컨텐츠)를 알아야하기에 private로 멤버 변수를 설정해준다.

무언가를 변경시킬때 필요한 내용(내가 설정해준 정보)을 물고 돌아 다니는 녀석!

package com.sparta.week03.domain;

import lombok.Getter;

@Getter
public class MemoRequestDto {
    private String username;
    private String contents;
}

서비스를 만들어보자

  • Memoservice를 만들자, 수정하는 기능이 있기때문에 service에 해당하는 패키지를 만들어서 이에 맞는 클래스도 작성해보자

메모를 업데이트해주기 위해서는 두 단계가 필요한데, 1번은 필요한 녀석을 찾고, 2는 그녀석의 정보를 업데이트해줘야한다.
필요한 녀석을 찾으려면 find를 사용하게 되는데 이때는 repository가 필요하다.
그래서 rerpository를 생성해주고 findbyid를 사용하는데, 항상 스프링에는 이런 아이디가 없을때의 어떻게 할 것이냐를 스프링에게 알려줘야 한다. orElseThrow를 통해서 뭔가 없으면 오류를 발생 시키라고 한다.

    public Long update(Long id, MemoRequestDto requestDto) {
        Memo memo = memoRepository.findById(id).orElseThrow(
                () -> new IllegalArgumentException("아이디가 존재하지 않습니다.")
        );
        memo.update(requestDto);
        return memo.getId();
    }

여기서 memoRepository를 그냥 둬버리면 spring에서는 애가 MemoService인지 아닌지를 잘 모르기때문에 final을 붙여서 꼭 필요한 녀석이라는 것을 알려줘야 한다. 또한 추가로
@RequiredArgsConstructor을 통해서 final로 선언된 녀석을 같이 넣어달라고 spring에게 얘기해주고 @Serivce를 통해서 spring에게 말해준다.
추가로 DB에 포함될수있도록 @Transactional을 사용하여 spring에게 말해준다.

Controller 만들기

repository service를 만들었으니 이제 controller을 만들 차례이다.

package com.sparta.week03.controller;

import com.sparta.week03.domain.Memo;
import com.sparta.week03.domain.MemoRepository;
import com.sparta.week03.domain.MemoRequestDto;
import com.sparta.week03.service.MemoService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

import java.util.List;


@RequiredArgsConstructor
@RestController
public class MemoController {
    private final MemoRepository memoRepository; //CRD에는 레포가 필요
    private final MemoService memoSerive; //업데이트에는 서비스가 필요


    @PostMapping("/api/memos")
    public Memo createMemo(@RequestBody MemoRequestDto requestDto){
        Memo memo = new Memo(requestDto);
        return memoRepository.save(memo);
    }

    @GetMapping("/api/memos")
    public List<Memo> readMemo(){
        return memoRepository.findAllByOrderByModifiedAtDesc();
    }

    @DeleteMapping("/api/memos/{id}")
    public Long deleteMemo(@PathVariable Long id){
        memoRepository.deleteById(id);
        return id;
    }


}

처음에 post를 할때 에러나 갔다. 왜냐 보았더니 요청이 왔을때 body안에 있는 내용을 DTO에 넣어 주는 @RequestBody(요청이들어왔을때 BODY안에 들어오는 REQUEST DTO에 넣어주는 녀석) 어노테이션이 빠졌기 때문이다. +실수가 많다니까 잘 생각해보자

자 다음으로는 아이디가 1인 녀석을 DELETE를 실행해보자

1이 나왔고, 다시 GET으로 요청하면 빈목록이 보인다. 잘 삭제됨을 확인할 수있다.

profile
기록해야 (살아)남는다 !

0개의 댓글