본문 바로가기
스프링

2주차- API

by Rudy 2021. 7. 13.

1. RDBMS

컴퓨터에 정보를 저장하고 관리하는 기술

 

H2: 인 메모리 데이터베이스. 서버가 멈추면 데이터가 모두 삭제됨. 서버가 작동하는 동안에만 데이터가 저장됨.

 

MySQL: 서비스를 배포할 때 사용할 데이터베이스

 

스프링을 작동시킨 뒤에 웹 주소창에 localhost:8080/h2-console 을 입력하면 아래와 같은 창이 뜬다. 

여기서 Connect 버튼을 눌러주고, 조금 기다리면 웹콘솔이 정상적으로 뜬다.

*JDBC URL은 jdbc:h2:mem:testdb 로 설정해주어야 Connect가 된다.

 

웹 콘솔창

 

2. SQL 연습

 

-Table courses 생성하기

 

CREATE TABLE IF NOT EXISTS courses (
    id bigint(5) NOT NULL AUTO_INCREMENT, 
    title varchar(255) NOT NULL,
    tutor varchar(255) NOT NULL,
    PRIMARY KEY (id)
);
CREATE TABLE IF NOT EXISTS students (
    id bigint(5) NOT NULL AUTO_INCREMENT, 
    name varchar(255) NOT NULL,
    age varchar(255) NOT NULL,
    PRIMARY KEY (id)
);

-데이터 삽입하기

 

INSERT INTO courses (title, tutor) VALUES
    ('웹개발의 봄, Spring', '남병관'), ('웹개발 종합반', '이범규');
INSERT INTO students (name, age) VALUES
    ('Sakuma Ritsu', '18'), ('Sena Izumi', '18');

-데이터 조회하기

 

SELECT * FROM courses;

3. JPA

 

SQL을 쓰지 않고 데이터를 생성, 조회, 수정, 삭제 할 수 있도록 해주는 번역기

 

domain 패키지 생성-> Courses.java 생성-> CourseRepository.java를 interface로 생성

 

*Courses.java

@NoArgsConstructor // 기본생성자를 대신 생성해줍니다.
@Entity // 테이블임을 나타냅니다.
public class Course {

    @Id // ID 값, Primary Key로 사용하겠다는 뜻입니다.
    @GeneratedValue(strategy = GenerationType.AUTO) // 자동 증가 명령입니다.
    private Long id;

    @Column(nullable = false) // 컬럼 값이고 반드시 값이 존재해야 함을 나타냅니다.
    private String title;

    @Column(nullable = false)
    private String tutor;

    public String getTitle() {
        return this.title;
    }

    public String getTutor() {
        return this.tutor;
    }

    public Course(String title, String tutor) {
        this.title = title;
        this.tutor = tutor;
    }
}

4. 생성일자, 수정일자

 

domian 패키지에 Timestampled.java 생성

 

package com.day0922.week02.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 // 상속했을 때, 컬럼으로 인식하게 합니다.
@EntityListeners(AuditingEntityListener.class) // 생성/수정 시간을 자동으로 반영하도록 설정
public abstract class Timestamped {

    @CreatedDate // 생성일자임을 나타냅니다.
    private LocalDateTime createdAt;

    @LastModifiedDate // 마지막 수정일자임을 나타냅니다.
    private LocalDateTime modifiedAt;
}

abstract는 상속으로만 쓴다고 알려주는 것

 

Course.java에 public class 옆에 Course extends Timestamped를 추가

 

 Week02Application.java에 @EnableJpaAuditing 추가

h2-console에서 select * from course 를 입력하면 생성일자와 수정일자를 확인할 수 있다.

 

5. JPA 심화

 

*Week02Application.java

 

package com.day0922.week02;

import com.day0922.week02.domain.Course;
import com.day0922.week02.domain.CourseRepository;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

import java.util.List;

@EnableJpaAuditing
@SpringBootApplication
public class Week02Application {

    public static void main(String[] args) {
        SpringApplication.run(Week02Application.class, args);
    }

    // Week02Application.java 의 main 함수 아래에 붙여주세요.
    @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());
            }

// 데이터 하나 조회하기
            Course course = repository.findById(1L).orElseThrow(
                    () -> new IllegalArgumentException("해당 아이디가 존재하지 않습니다.")
            );

    }

    ;
}
}

Course.java에서 getId 추가

 

6. Service 만들기

 

course 클래스에 update 메소드 추가

 

src > main > java > com.sparta.week02 > service 패키지 생성

 

* Courseservice.java

@Service // 스프링에게 이 클래스는 서비스임을 명시
public class CourseService {

		// final: 서비스에게 꼭 필요한 녀석임을 명시
    private final CourseRepository courseRepository;

		// 생성자를 통해, Service 클래스를 만들 때 꼭 Repository를 넣어주도록
		// 스프링에게 알려줌
    public CourseService(CourseRepository courseRepository) {
        this.courseRepository = courseRepository;
    }

    @Transactional // SQL 쿼리가 일어나야 함을 스프링에게 알려줌
    public Long update(Long id, Course course) {
        Course course1 = courseRepository.findById(id).orElseThrow(
                () -> new IllegalArgumentException("해당 아이디가 존재하지 않습니다.")
        );
        course1.update(course);
        return course1.getId();
    }
}

@Transactional 때문에 Course 클래스 안에 update 메소드를 만들고 (전달받는 내가 변경할 정보를 가져오는 녀석) 내 정보를 바꿔주면 자동으로 데이터베이스에 적용된다.

 

7. 업데이트 실행하기 

 

*Week02Application.java

package com.day0922.week02;

import com.day0922.week02.domain.Course;
import com.day0922.week02.domain.CourseRepository;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

import java.util.List;

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

            Course new_course = new Course("웹개발의 봄, Spring", "임민영");
            courseService.update(1L, new_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());
            }
        };
    }
}

CourseService의 업데이트 기능을 활용하면 기존의 데이터가 아니라 새로운 데이터를 사용할 수 있다. 

 

8. Delete 실행하기

 

courseRepository.deleteAll(); 을 마지막에 추가해주면 된다.

 

9. Lombok, DTO

 

Lombok: 코드를 절약하기 위한 녀석

 

Ctrl+Alt+S 를 눌러서 Annotation Process를 검색하고 Enable Annotation Processing 체크박스에 체크를 한 후, Ok를 눌러준다.

 

shift를 두 번 누른 뒤, Plugins를 검색, Lombok을 설치한다.

 

그리고 그 후에 Course 클래스에서 Getter를 전부 삭제하면, 오류가 나는데 Course 클래스의 상단에 @Getter 를 추가해주면 Lombok이 자동으로 Getter를 생성해줘서 오류가 사라지게 된다.

 

DTO: read, update를 할 때 테이블을 막 건드리게 되는 경우에 다른 사람이 변경을 하는 경우가 생긴다면 시스템에 오류가 생길 수도 있는데, 그것을 완충해주는 것이 DTO

 

domain 패키지에 코스 데이터를 물고 다니는 녀석인 CourseRequestDto.java를 생성한다.

 

package com.day0922.week02.domain;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;

@Setter
@Getter
@RequiredArgsConstructor

public class CourseRequestDto(String title, String tutor) {
    private String title;
    private String tutor;
}

*CourseService.java

package com.day0922.week02.service;

import com.day0922.week02.domain.Course;
import com.day0922.week02.domain.CourseRepository;
import com.day0922.week02.domain.CourseRequestDto;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;

@Service // 스프링에게 이 클래스는 서비스임을 명시
public class CourseService {

    // final: 서비스에게 꼭 필요한 녀석임을 명시
    private final CourseRepository courseRepository;

    // 생성자를 통해, Service 클래스를 만들 때 꼭 Repository를 넣어주도록
    // 스프링에게 알려줌
    public CourseService(CourseRepository courseRepository) {
        this.courseRepository = courseRepository;
    }

    @Transactional // SQL 쿼리가 일어나야 함을 스프링에게 알려줌
    public Long update(Long id, CourseRequestDto requestDto) {
        Course course1 = courseRepository.findById(id).orElseThrow(
                () -> new IllegalArgumentException("해당 아이디가 존재하지 않습니다.")
        );
        course1.update(requestDto);
        return course1.getId();
    }
}

 

*Course.java

package com.day0922.week02.domain;

import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@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(String title, String tutor) {
        this.title = title;
        this.tutor = tutor;

    }
    public void update(CourseRequestDto requestDto) {
        this.title = requestDto.getTitle();
        this.tutor = requestDto.getTutor();
    }
}

 

10. API-GET(조회)

 

controller라는 새로운 패키지 생성->CourseController.java 생성

 

*CourseController.java

package com.day0922.week02.controller;

import com.day0922.week02.domain.Course;
import com.day0922.week02.domain.CourseRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RequiredArgsConstructor
@RestController
public class CourseController {

    private final CourseRepository courseRepository;

    @GetMapping("/api/courses")
    public List<Course> getCourses() {
        return courseRepository.findAll();
    }
}

*Week02Application.java

package com.day0922.week02;

import com.day0922.week02.domain.Course;
import com.day0922.week02.domain.CourseRepository;
import com.day0922.week02.domain.CourseRequestDto;
import com.day0922.week02.service.CourseService;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

import java.util.List;

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

            Course new_course = new Course("웹개발의 봄, Spring", "임민영");
            CourseRequestDto requestDto=new CourseRequestDto();
            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();
        };
    }
}

 

*Course.java

package com.day0922.week02.domain;

import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@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(String title, String tutor) {
        this.title = title;
        this.tutor = tutor;

    }
    public void update(CourseRequestDto requestDto) {
        this.title = requestDto.getTitle();
        this.tutor = requestDto.getTutor();
    }
}

 

컴파일 후에

http://localhost:8080/api/courses

에 접속하면 아래와 같이 나온다.

 

Put 할 때 CourseController.java에 추가

 

@PutMapping("/api/courses/{id}")
public Long updateCourse(@PathVariable Long id, @RequestBody CourseRequestDto requestDto) {
    return courseService.update(id, requestDto);
}

 

 

'스프링' 카테고리의 다른 글

Web server failed to start. Port 8080 was already in use.  (0) 2022.05.16
5주차-완성: 익명 타임라인 페이지  (0) 2021.08.03
4주차  (0) 2021.07.31
스프링 3주차  (0) 2021.07.20
Spring 1주차-자바 기초문법  (0) 2021.07.06

댓글