spring기초 3주차 정리

Today Jeeho Learned·2022년 6월 8일
0

Spring

목록 보기
6/31
post-thumbnail

1. API 설계하기

  • API URL에서는 항상 복수형으로 써주기!

2. Repository 생성하기

(1) Memo 클래스 생성하기

MEMO 클래스는 작성자이름, 메모내용으로 구성되어있다.
domain 패키지를 만들어서 MEMO.java 클래스를 만들어준다.

@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();
    }
}

클래스를 만들때는 각 db의 컬럼에 대응되는 것들과 함께, @entity를 사용해주고, @id값이나 @Column값들을 넣어주면서 표시해준다.

클래스의 첫 글자는 항상 대문자로!

(2) Timestamped 클래스 생성하기


@MappedSuperclass // Entity가 자동으로 컬럼으로 인식합니다.
@EntityListeners(AuditingEntityListener.class) // 생성/변경 시간을 자동으로 업데이트합니다.
public abstract class Timestamped {

    @CreatedDate
    private LocalDateTime createdAt;

    @LastModifiedDate
    private LocalDateTime modifiedAt;
}

abstract를 써주면서 다른 데서 상속이 되어야만 빵틀을 만들수있는 클래스라는 것을 명시해준다.

(3) Repository클래스 생성하기

public interface MemoRepository extends JpaRepository<Memo, Long> {
	List<Memo> findAllByOrderByModifiedAtDesc();
}

interface로 생성해준다. interface는 클래스에서 멤버변수가 없는 클래스이다!
memorepository가 jparepository를 가져다 쓸 것이라는 것들 명시하고 memo라는 클래스에서 id는 long인 녀석에 대해서 가져다가 쓸 것이라고 명시한다.

findAllByOrderByModifiedAtDesc();에는 뭘까 ?
전부다 찾을 것인데, 최신순으로 정리해달라는 명령어다.
jpa 공식홈페이지에보면 keyword와 sample별로 jpa 명령어가 있으니 필요할때 잘 살펴보자.

(2) MemoRequestDto 생성하기

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

memo클래스와 같은 정보를 담는 그릇이기때문에 같은 멤버변수로 private로 생성해주고 위에 @getter을 선언해주면서 작성해주면 된다.

(3) Service 생성하기

service는 주로 변경기능에 해당된다. 전에 update때 사용했었던것이 기억난다.

@RequiredArgsConstructor
@Service
public class MemoService {

    private final MemoRepository memoRepository;

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

메소드를 만들어줘야하는데, update메소드를 생성해보자
메소드형식은 public 반환타입 메소드이름(재료){ }으로 만들어야한다.
update시킬때는 1.변경시킬 녀석의 id, 2.변경시킬 내용으로 2가지가 필요하다.
id는 long 타입이었고, 변경시킬때 필요한 정보를 가지고 다니는 녀석을 DTO라고한다.

업데이트할때 2가지 단계가 필요한데, 첫번째로는 필요한 녀석을 찾고, 그 녀석의 정보를 업데이트 해줘야 한다.

그래서 memoservice의 멤버변수로 MemoRepository를 사용하고, 이것을 통해서 id를 기준으로 찾아준다. 추가로 여기에 이정보가 없을때의 경우도 스프링에게 항상 알려줘야한다.

찾고나서 결과물은 Memo memo에 반환해주고, memo의 필요한 정보를 dto에있는 값으로 update해준다.

update메소드는 어떤 녀석이 업데이트가 됐는지 그 id를 돌려주는 것이기때문에 return id를 해주면 된다. id를 돌려주기 때문에 메소드의 반환타입도 long으로 주면 된다.

그리고 memo class로 돌아가서 update메소드를 추가해줘야한다.

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

추가로 MemoService를 이용할때, memo repository를 그냥 두면 스프링이 이녀석이 service인지 아닌지를 잘 모르기때문에 final를 써줘서 꼭 필요하다고 얘기해줘야 한다.

또한 @RequiredArgsConstructor를 사용해주면서 final에 명시된 것을 생성시에 같이 넣어줄수있도록 스프링에게 얘기해주는 것이다.

@Transactional를 통해서 db에 직접 반영되도록해주는 어노테이션이다.

(4) Controller 생성하기

생성POST(반환:MEMO) 조회GET(반환:LIST<MEMO>) 삭제DELETE(반환:long) 변경PUT(반환:long) api를 만들 것이다.

@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();
    }

    @PutMapping("/api/memos/{id}")
    public Long updateMemo(@PathVariable Long id, @RequestBody MemoRequestDto requestDto) {
        memoSerive.update(id, requestDto);
        return id;
    }

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

}

update에는 service가 필요하고 나머지는 repository가 필요하기때문에 멤버변수로 가져온다. 이때도 꼭 final과 requireargsconstructor 생성자를 사용해준다.
또한 @restcontroller를 붙여주면서 스프링에게 컨트롤러임을 알려준다.

삭제하거나 수정할때 주소로 {id}값을 같이 받는데, 이 id값을 변수로 받기 위해서 이때 @PathVariable를 사용해준다.

++ 추가로 create나 update에서 클라이언트가 데이터를 보낼 때, 이 데이터를 정확히 requestDto에 넣어주기 위해서는 @RequestBody라는 것이 필요하다.
요청이 날아올때 Body라는 녀석이 들어있는 거를 requestdto에 넣어달라는 것이다.

Rest Api를 개발시 클라이언트와 데이터를 JSON 으로 주고받고 하는데 이때 사용되는 어노테이션 중 하나가 @RequestBody 어노테이션 입니다.
클라이언트에서 request data를 body에 담고 content-type을 application/json 으로 설정을 해야합니다.

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

0개의 댓글