Spring

[Spring] JPA, CRUD

jelliclesu 2024. 7. 17. 20:52

  • JPA
    : SQL을 사용하지 않고 데이터를 생성, 조회, 수정, 삭제할 수 있도록 해주는 번역기
    🥲JPA가 없다면🥲
    JAVA 짜다가 SQL 짜고, 그걸 잘 맞춰 넣어야해서 매우 복잡
    • Domain - Table, Repository - SQL 로 생각하면 됨

 

  • H2를 이용해 테이블을 생성했던 것을 JAVA로 표현한다면?
    1. src > main > java > com.sparta.week02 에 domain 패키지 생성
    2. Course.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 Long getId() {
          	return this.id;
          }
          
          public String getTitle() {
              return this.title;
          }
      
          public String getTutor() {
              return this.tutor;
          }
      
          public Course(String title, String tutor) {
              this.title = title;
              this.tutor = tutor;
          }
      }
    3. CourseRepository.java 인터페이스 생성
      public interface CourseRepository extends JpaRepository<Course, Long> { 
      // Course의 Id는 Long타입
      }
      • Interface
        : Class에서 member가 빠진, method 모음집
        ‼️JPA는 Repository를 통해서만 사용 가능

    4. SQL이 보이도록 application.properties 세팅
      spring.jpa.show-sql=true
      spring.datasource.url=jdbc:h2:mem:testdb;MODE=MYSQL
    5. main 함수 아래에 JPA 실행 코드 추가
      @Bean
      public CommandLineRunner demo(CourseRepository repository) {
          return (args) -> {
      
          };
      }
  • 상속
    : extends - 클래스의 상속이미 만들어둔 걸 가져다 쓴다고 선언하는 것
    • Timestamped
      DB의 기본은 "생성일자"와 "수정일자"를 필드로 가지는 것
      • Timestamped.java 생성
        @MappedSuperclass // 상속했을 때, 컬럼으로 인식하게 합니다.
        @EntityListeners(AuditingEntityListener.class) // 생성/수정 시간을 자동으로 반영하도록 설정
        public class Timestamped {
        
            @CreatedDate // 생성일자임을 나타냅니다.
            private LocalDateTime createdAt;
        
            @LastModifiedDate // 마지막 수정일자임을 나타냅니다.
            private LocalDateTime modifiedAt;
        }
      • Course.javaextends 추가
        class Course extends Timestamped {
      • Week02Application.java@EnableJpaAuditing 추가
        @EnableJpaAuditing // 생성일자, 수정일자 자동으로 업데이트
        @SpringBootApplication
        public class Week02Application {
      • http://localhost:8080/h2-console 접속해서 확인
        SELECT * FROM course;
  • JPA 심화
    • CRUD: 정보관리의 기본 기능으로 Create(생성), Read(조회), Update(변경), Delete(삭제)을 뜻함 
    • Create & Read
      : Repository의 savefindAll 등 이용(main 함수에 작성)
      repository.save(new Course("Spring", "곽두필"));
      
      // 데이터 전부 조회하기(Read)
      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());
      }
      
      // 데이터 하나 조회하기(Read)
      Course course = repository.findById(1L).orElseThrow(
          () -> new IllegalArgumentException("해당 아이디가 존재하지 않습니다.")
      );
    • Service
      ➡️ Update와 Delete 전에 다루어야 하는 개념
      • 스프링의 구조
        1. Controller: 가장 바깥 부분, 요청/응답 처리
        2. Service: 중간 부분, 실제 중요한 작동이 많이 일어나는 부분
        3. Repo: 가장 안쪽 부분, DB와 맞닿아 있음(Repository, Entity)
      • Service 만들기
        1. Course.javaupdate 추가
          public void update(Course course) {
              this.title = course.title;
              this.tutor = course.tutor;
          }
        2. src > main > java > com.sparta.week02 > service 패키지 생성
        3. 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();
              }
          }
    • Update & Delete (main 함수에 작성)
      @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());
              }
      		
              // Update
              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());
              }
      		
              // Delete
              courseRepository.deleteAll();
          };
      }