2022년 3월 29일(화) ~ 30일(수)
[스파르타코딩클럽] 웹개발의 봄, Spring 2주차 과정 - 2
// domain.Course.java Method에 추가
public void update(Course course) {
    this.title = course.title;
    this.tutor = course.tutor;
}
// service.CourseService.java
@RequiredArgsConstructor
@Service // 스프링에게 이 클래스는 서비스임을 명시
public class CourseService {
    // final: 서비스에게 꼭 필요한 녀석임을 명시 / 한번 값이 부여되면 변경될 수 없다.
    private final CourseRepository courseRepository;
      // @RequiredArgsConstructor로 대체
//    // 생성자를 통해, Service 클래스를 만들 때 꼭 Repository를 넣어주도록
//    // 스프링에게 알려줌
//    public CourseService(CourseRepository courseRepository) {
//        this.courseRepository = courseRepository;
//    }
// 위의 두 과정을 통해 CourseRepository 가 내가 언제든 쓸 수 있게 스프링이 생성해서 넘겨줌
    //업데이트 부분
   @Transactional // SQL 쿼리가 일어나야 함을 스프링에게 알려줌 // 업데이트 시 반영하게 함
   // 업데이트 시 필요한 것 : id, 업데이트 할 정보를 가져올 녀석 (title, tutor 정보가 들어있음)
    public Long update(Long id, CourseRequestDto requestDto) {
        Course course1 = courseRepository.findById(id).orElseThrow(
                () -> new IllegalArgumentException("해당 아이디가 존재하지 않습니다.")
        );
        course1.update(requestDto);
        return course1.getId();
    }
}	@Bean
    public CommandLineRunner demo(CourseRepository repository) {
        return (args) -> {
            // 데이터 저장하기
            repository.save(new Course("프론트엔드의 꽃, 리액트", "임민영"));
            // 데이터 전부 조회하기
            List<Course> courseList = repository.findAll();
            for (int i = 0; i < courseList.size(); i++) {
                Course course = courseList.get(i);
                System.out.println(course.getId());
                System.out.println(course.getTitle());
                System.out.println(course.getTutor());
            }
            // 데이터 하나 조회하기
            // findById 아이디로 찾기
            // orElseThrow 없을 때 할꺼 작성
            // NullPointerException 가리킬게 없을 때 대처방법
            Course course = repository.findById(2L).orElseThrow(
                    () -> new NullPointerException("아이디가 존재하지 않습니다.")
            );
        };
    }@Bean
public CommandLineRunner demo(CourseRepository courseRepository, CourseService courseService) {
    return (args) -> {
        courseRepository.save(new Course("프론트엔드의 꽃, 리액트", "임민영"));
        System.out.println("데이터 인쇄");
        List<Course> courseList = courseRepository.findAll();
        for (int i=0; i<courseList.size(); i++) {
            Course course = courseList.get(i);
            System.out.println(course.getId());
            System.out.println(course.getTitle());
            System.out.println(course.getTutor());
        }
        CourseRequestDto requestDto = new CourseRequestDto("웹개발의 봄, Spring", "임민영");
        courseService.update(1L, requestDto);
        courseList = courseRepository.findAll();
        for (int i=0; i<courseList.size(); i++) {
            Course course = courseList.get(i);
            System.out.println(course.getId());
            System.out.println(course.getTitle());
            System.out.println(course.getTutor());
       }
    };
}	courseRepository.deleteAll(); // 삭제하는 부분자바 프로젝트를 진행하는데 거의 필수적으로 필요한 메소드/생성자 등을 자동생성해줌으로써 코드를 절약할 수 있도록 도와주는 라이브러리
설치 : project 생성시 진행했음
환경설정
사용
-> DB에 연결된 class는 그대로 두고, 물고다니는 class는 따로 만들 가능성이 부각됨
// domain.CourseRequestDto.java
@NoArgsConstructor
@Getter
public class CourseRequestDto {
    private String title;
    private String tutor;
    public CourseRequestDto(String title, String tutor) {
        this.title = title;
        this.tutor = tutor;
    }
}// service.CourseService
@RequiredArgsConstructor
@Service // 스프링에게 이 클래스는 서비스임을 명시
public class CourseService {
    // final: 서비스에게 꼭 필요한 녀석임을 명시 / 한번 값이 부여되면 변경될 수 없다.
    private final CourseRepository courseRepository;
    // @RequiredArgsConstructor로 대체
//    // 생성자를 통해, Service 클래스를 만들 때 꼭 Repository를 넣어주도록
//    // 스프링에게 알려줌
//    public CourseService(CourseRepository courseRepository) {
//        this.courseRepository = courseRepository;
//    }
    // 위의 두 과정을 통해 CourseRepository 가 내가 언제든 쓸 수 있게 스프링이 생성해서 넘겨줌
    //업데이트 부분
   @Transactional // SQL 쿼리가 일어나야 함을 스프링에게 알려줌 // 업데이트 시 반영하게 함
   // 업데이트 시 필요한 것 : id, 업데이트 할 정보를 가져올 녀석 (title, tutor 정보가 들어있음)
    public Long update(Long id, CourseRequestDto requestDto) {
        Course course1 = courseRepository.findById(id).orElseThrow(
                () -> new IllegalArgumentException("해당 아이디가 존재하지 않습니다.")
        );
        course1.update(requestDto);
        return course1.getId();
    }
}
// domain.Course.java
@Getter // Getter 코드를 대체
@NoArgsConstructor // 기본생성자를 대신 생성해줍니다.
@Entity // 테이블임을 나타냅니다.
public class Course extends Timestamped{
    @Id // ID 값, Primary Key로 사용하겠다는 뜻입니다.
    @GeneratedValue(strategy = GenerationType.AUTO) // 자동 증가 명령입니다.
    private Long id;
    @Column(nullable = false) // 컬럼 값이고 반드시 값이 존재해야 함을 나타냅니다.
    private String title;
    @Column(nullable = false)
    private String tutor;
    public Course(CourseRequestDto requestDto) {
        this.title = requestDto.getTitle();
        this.tutor = requestDto.getTutor();
    }
    //생성자
   public Course(String title, String tutor) {
        this.title = title;
        this.tutor = tutor;
    }
    // 업데이트트
   public void update(CourseRequestDto requestDto) {
        this.title = requestDto.getTitle();
        this.tutor = requestDto.getTutor();
    }
}
// Application
@EnableJpaAuditing // 생성, 수정 일자에따라 날짜가 자동으로 업데이트
@SpringBootApplication
public class Week02Application {
    public static void main(String[] args) {
        SpringApplication.run(Week02Application.class, args);
    }
    @Bean
    public CommandLineRunner demo(CourseRepository courseRepository, CourseService courseService) {
        return (args) -> {
            courseRepository.save(new Course("프론트엔드의 꽃, 리액트", "임민영"));
            System.out.println("데이터 인쇄");
            List<Course> courseList = courseRepository.findAll();
            for (int i=0; i<courseList.size(); i++) {
                Course course = courseList.get(i);
                System.out.println(course.getId());
                System.out.println(course.getTitle());
                System.out.println(course.getTutor());
            }
            CourseRequestDto requestDto = new CourseRequestDto("웹개발의 봄, Spring", "임민영");
            courseService.update(1L, requestDto);
            courseList = courseRepository.findAll();
            for (int i=0; i<courseList.size(); i++) {
                Course course = courseList.get(i);
                System.out.println(course.getId());
                System.out.println(course.getTitle());
                System.out.println(course.getTutor());
            }
            courseRepository.deleteAll();
        };
    }
}API: 클라이언트 - 서버 간의 약속
클라이언트가 정한대로 서버에게 요청(Request)을 보내면,
서버가 요구사항을 처리하여 응답(Response)을 반환합니다.
REST: 주소에 명사, 요청 방식에 동사를 사용함으로써 의도를 명확히 드러냄을 의미함
주소 요청시 주의 사항
ARC(Advanced REST Client) : API 만들고 나서 테스트를 돕는 tool

Controller 코드
// controller.CoursesController.java
@RequiredArgsConstructor
@RestController // json으로 응답하기
public class CourseController {
    private final CourseRepository courseRepository;
    private final CourseService courseService;
    // 어노테이션(Annotation)을 통해해같은 소라도 방식이 다름을 구분합니다.
    // Get 방식
    @GetMapping("/api/courses")
    public List<Course> getCourses() {
        return courseRepository.findAll();
    }
    // Post 방식 
    @PostMapping("/api/courses")
    public Course createCourse(@RequestBody CourseRequestDto requestDto) {
        // @RequestBody:  POST, PUT 방식에서 API에서 넘어오는 데이터를 잘 받으려면 RequestBody의 형태로 받아야함
        
        // requestDto 는, 생성 요청을 의미합니다.
        // 강의 정보를 만들기 위해서는 강의 제목과 튜터 이름이 필요하잖아요?
        // 그 정보를 가져오는 녀석입니다.
        // 저장하는 것은 Dto가 아니라 Course이니, Dto의 정보를 course에 담아야 합니다.
        // 잠시 뒤 새로운 생성자를 만듭니다.
        Course course = new Course(requestDto);
        // JPA를 이용하여 DB에 저장하고, 그 결과를 반환합니다.
        return courseRepository.save(course);
    }
    
    // Put 방식
    @PutMapping("/api/courses/{id}")
    public Long updateCourse(@PathVariable Long id, @RequestBody CourseRequestDto requestDto) {
        return courseService.update(id, requestDto);
    }
    
    // Delete 방식
    @DeleteMapping("/api/courses/{id}")
    public Long deleteCourse(@PathVariable Long id) {
        courseRepository.deleteById(id);
        return id;
    }