왜 사용하는지 어떤 원리로 동작하는지 이해하는게 중요
리포지토리를 왜사용하지?
하는역할
어떻게 동작하는지
리포지토리:
데이터베이스와 데이터를 주고받기위한 인터페이스를 정의한 부분.
출처:https://whitepro.tistory.com/265
역할:
Entity에 의해 생성된 DB에 접근하는 메서드(ex) findAll()) 들을 사용하기 위한 인터페이스이다.
DB에 접근하는 모든 코드가 모여있다.
@Entity : 클래스 위에 선언하여 이 클래스가 엔티티임을 알려준다. 이렇게 되면 JPA에서 정의된 필드들을 바탕으로 데이터베이스에 테이블을 만들어준다.
엔티티를 선언함으로써 데이터베이스 구조를 만들었다면, 여기에 어떤 값을 넣거나, 넣어진 값을 조회하는 등의 CRUD(Create, Read, Update, Delete)를 해야 쓸모가 있는데, 이것을 어떻게 할 것인지 정의해주는 계층
왜 사용할까?
Service단에는 비즈니스 로직에 관련된 코드만 들어가게 된다.
Repository에는 DB에 접근하는 모든 코드를 담고 있다.
그러니까 DB접근 문제인지, 비즈니스 로직문제인지에 따라서 확인할 곳이 정해진다. 유지보수가 쉬워진다는 얘기다.
동작 방법
JpaRepository를 상속받도록 함으로써 기본적인 동작이 모두 가능해진다. JpaRepository는 어떤 엔티티를 메서드의 대상으로 할지를 다음 키워드로 지정한다. JpaRepository<대상으로 지정할 엔티티, 해당 엔티티의 PK의 타입>.
이렇게 extends를 통해서 상속받고나면, 해당 레포지토리의 객체를 이용해서 기본적으로 제공되는 메서드(save(), findAll(), get()) 등을 사용할 수 있게 된다.
출처:https://jobc.tistory.com/120
method | 기능 |
save() | 레코드 저장 (insert, update) |
findOne() | primary key로 레코드 한개 찾기 |
findAll() | 전체 레코드 불러오기. 정렬(sort), 페이징(pageable) 가능 |
count() | 레코드 갯수 |
delete() | 레코드 삭제 |
TodoRepository 생성 후
JpaRepository를 상속, Repository 어노테이션을 사용했다.
- 서비스단 구현
-리스트 목록에 아이템 추가.
엔티티 타입을 새로 선언하고 (todoEntity)
request로 요청받은 정보들을
todoEntity에 setter로 저장받는다.( @Data를 Entity에서 선언했기 때문에 따로 setter코드가 TodoEntity파일에 없어도 사용가능)
그 후 TodoService의 필드멤버인 todoRepository의 save메소드로 이 엔티티를 저장받고 리턴.
save 메소드는 대표키가 null이면 데이터베이스에 저장해주는걸로 알고 있다.
- 리스트 목록 중 특정 아이템 조회
리포지토리의 findById를 사용해서 조회하고
orElseTHrow를 사용해서 값이 없으면 Not Found를 날리도록 설정.
-리스트 전체목록 조회
리포지토리의 findAll메소드를 활용한 뒤 리턴. ( 모든 엔티티값들이 리턴되니까 List형식으로 반환한다.)
-리스트 목록 중 특정 아이템을 수정.
특정 아이템을 가져오기 위해 searchById메소드를 사용한다.
그 후 가져온 엔티티 내부 값이 null이 아니면 요청받은 값으로 전부 변경한다.
그 후 리포지토리의 save메소드에 변경된 엔티티를 저장하고 리턴
-리스트목록 중 특정아이템 삭제
리포지토리의 deleteById메소드 활용
-리스트목록 중 모든아이템 삭제
리포지토리의 deleteAll메소드 활용
삭제 메소드라서 반환값이 없다.
컨트롤러 구현
컨트롤러 단
package org.example.controller;
import lombok.AllArgsConstructor;
import org.example.model.TodoEntity;
import org.example.model.TodoRequest;
import org.example.model.TodoResponse;
import org.example.service.TodoService;
import org.springframework.http.ResponseEntity;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.stream.Collectors;
@CrossOrigin
@AllArgsConstructor
@RestController
@RequestMapping("/")
public class TodoController {
private final TodoService service;
@PostMapping
public ResponseEntity<TodoResponse> create(@RequestBody TodoRequest request){
System.out.println("CREATE");
if (ObjectUtils.isEmpty(request.getTitle()))
return ResponseEntity.badRequest().build();
if (ObjectUtils.isEmpty(request.getOrder()))
request.setOrder(0L);
if (ObjectUtils.isEmpty(request.getCompleted()))
request.setCompleted(false);
TodoEntity result= this.service.add(request);
return ResponseEntity.ok(new TodoResponse(result));
//받은 result를 TodoResponse에 매핑
}
@GetMapping("{id}")
public ResponseEntity<TodoResponse> readOne(@PathVariable Long id) {
System.out.println("READ ONE");
TodoEntity result= this.service.searchById(id);
return ResponseEntity.ok(new TodoResponse(result) ) ;
}
@GetMapping
public ResponseEntity<List<TodoResponse>> readAll() {
System.out.println("READALL");
List<TodoEntity> list=this.service.searchAll();
List<TodoResponse> response=list.stream().map(TodoResponse::new)
.collect(Collectors.toList());
return ResponseEntity.ok(response);
}
@PatchMapping("{id}")
public ResponseEntity<TodoResponse> update(@PathVariable Long id, @RequestBody TodoRequest request){
System.out.println("UPDATE");
this.service.updateById(id,request);
TodoEntity result=this.service.updateById(id, request);
return ResponseEntity.ok(new TodoResponse(result));
}
@DeleteMapping("{id}")
public ResponseEntity<?> deleteOne(@PathVariable Long id){
System.out.println("DELETE");
this.service.deleteById(id);
return ResponseEntity.ok().build();
}
@DeleteMapping
public ResponseEntity<?> deleteAll(){
System.out.println("DELETE ALL");
this.service.deleteAll();
return ResponseEntity.ok().build();
}
}
메인쪽
package org.example;
import org.example.repository.TodoRepository;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class TodoServerApplication {
public static void main(String[] args) {
SpringApplication.run(TodoServerApplication.class, args);
}
}
Caused by: org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
이에러는 @SpringBootApplication 어노테이션 빠지니까 떴음
Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]
이 에러는 @PostMapping뒤에 ({"id})를 붙여서 뜬 에러
Caused by: java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'todoController' method
이에러는 리퀘스트 매핑을 잘못하면 생김.
.../java.exe'' finished with non-zero exit value
이런 에러가 생겨서
setting의 gradle의 Build and run using이랑 밑에 항목을 IntelliJ IDEA로 변경했음
api 실행확인을 위해서 postman 설치
https://www.todobackend.com/contribute.html
https://www.todobackend.com/client/index.html?https://todo-backend-catalyst.herokuapp.com/
프론트엔드 붙이기
https://www.todobackend.com/client/index.html? 여기 뒤에 만들어 놓은 url주소를 삽입( http://localhost:8080 )
그다음 아무단어나 치고 enter를 누르면 CREATE가 인텔리제이에서 정상적으로 동작된다.
체크표시를 클릭하면 UPDATE됨
'패스트캠퍼스 Spring강의 > 인텔리제이 가이드' 카테고리의 다른 글
2일차 - 단축키 기본 1,2, 응용 (0) | 2021.10.15 |
---|---|
ch.1 인텔리제이 시작 (0) | 2021.10.14 |