스프링 부트에서 JPA로 데이터베이스 다뤄보자

iseon_u·2023년 3월 22일
0

Book

목록 보기
4/16
post-thumbnail

CH03 - 스프링 부트에서 JPA로 데이터베이스 다뤄보자


ORM 은 객체를 매핑
SQL Mapper 는 쿼리를 매핑

Spring Data JPA

  • JPA 구현체
    • Hibernate
    • Eclipse Link
  • 구현체를 추상화 시킨 모듈
  • JPA ← Hibernate ← Spring Data JPA

Spring Data JPA 를 사용하는 이유

  • 구현체 교체의 용이성
    • Hibernate 외에 다른 구현체로 쉽게 교체하기 위해 사용
  • 저장소 교체의 용이성
    • 관계형 데이터베이스 외에 다른 저장소로 쉽게 교체하기 위해 사용

Domain 클래스

Posts.java

package com.pgrrr.book.springboot.domain.posts;

import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@Getter // 6
@NoArgsConstructor // 5
@Entity // 1
public class Posts {
    
    @Id // 2
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 3
    private Long id;
    
    @Column(length = 500, nullable = false) // 4
    private String title;
    
    @Column(columnDefinition = "TEXT",  nullable = false)
    private String content;
    
    private String author;

    @Builder // 7
    public Posts(String title, String content, String author) {
        this.title = title;
        this.content = content;
        this.author = author;
    }
}
  • 주요 어노테이션을 클래스에 가깝게 정렬
  • 실제 DB 테이블과 매칭될 클래스 (Entity 클래스)
  1. @Entity
    • 테이블과 링크될 클래스임을 나타낸다
    • 기본값으로 클래스의 카멜케이스 이름을 언더스코어 네이밍으로 테이블 이름 매칭
  2. @Id
    • 해당 테이블의 PK 필드를 나타낸다
  3. @GeneratedValue
    • PK의 생성 규칙을 나타낸다
    • 스프링 부트 2.0 에서는 GenerationType.IDENTITY 옵션을 추가해야만 auto_increment 가 된다
  4. @Column
    • 테이블의 칼럼을 나타내며 굳이 선언하지 않더라도 해당 클래스의 필드는 모두 칼럼이 된다
    • 기본값 외에 추가로 변경이 필요한 옵션이 있으면 사용
    • 문자열의 경우 VARCHAR(255)가 기본값인데 사이즈를 500으로 늘리고 싶거나 타입을 TEXT 로 변경하고 싶을 때 사용

웬만하면 Entity의 PK 는 Long 타입의 Auto_increment (MySQL 기준 bigint)

  1. @NoArgsConstructor
    • 기본 생성자 자동 추가
    • public Posts() {} 와 같은 효과
  2. @Getter
    • 클래스 내 모든 필드의 Getter 메소드를 자동 생성
  3. @Builder
    • 해당 클래스의 빌더 패턴 클래스를 생성
    • 생성자 상단에 선언 시 생성자에 포함된 필드만 빌더에 포함
  • Entity 클래스에서는 절대 Setter 메소드를 만들지 않는다
    • 대신 목적과 의도를 나타낼 수 있는 메소드를 추가

Setter 없이 DB에 값을 넣는 법

  • 생성자를 통해 최종 값을 채운 후 DB에 삽입
    • 값 변경시 해당 이벤트에 맞는 public 메소드 호출
    • 채워야 하는 필드가 무엇인지 명확하게 지정 불가
  • @Builder 를 통해 제공되는 빌더 클래스를 사용
    • 생성 시점에 값을 채워준다
    • 어느 필드에 어떤 값을 채울지 명확하게 지정 가능

DB Layer 접근자

PostsRepository.java

package com.pgrrr.book.springboot.domain.posts;

import org.springframework.data.jpa.repository.JpaRepository;

public interface PostsRepository extends JpaRepository<Posts, Long> {
    
}
  • 인터페이스로 생성
  • JpaRepository<Entity 클래스, PK 타입> 을 상속
    • 기본적인 CRUD 메소드 자동 생성
  • @Repository 불필요
  • Entity 클래스와 함께 위치시킨다

Spring Data JPA 테스트 코드

package com.pgrrr.book.springboot.domain.posts;

import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

@RunWith(SpringRunner.class)
@SpringBootTest
public class PostsRepositoryTest {
    
    @Autowired
    PostsRepository postsRepository;
    
    @After // 1
    public void cleanup() {
        postsRepository.deleteAll();
    }
    
    @Test
    public void 게시글저장_불러오기() {
        //given
        String title = "테스트 게시글";
        String content = "테스트 본문";

        postsRepository.save(Posts.builder() // 2
                .title(title)
                .content(content)
                .author("pgrrr119@gmail.com")
                .build());
        
        //when
        List<Posts> postsList = postsRepository.findAll(); // 3
        
        //then
        Posts posts = postsList.get(0);
        assertThat(posts.getTitle()).isEqualTo(title);
        assertThat(posts.getContent()).isEqualTo(content);
    }

}
  1. @After
    • JUnit 에서 단위 테스트가 끝날 때마다 수행되는 메소드를 지정
    • 보통 배포 전 전체 테스트를 수행할 때 테스트간 데이터 침범을 막기 위해 사용
  2. postsRepository.save
    • 테이블 posts 에 insert/update 쿼리를 실행
    • id 값이 있다면 update 가 없다면 insert 쿼리가 실행
  3. postsRepository.findAll
    • 테이블 posts 에 있는 모든 데이터를 조회해오는 메소드

실제 실행된 쿼리 확인

application.properties

spring.jpa.show-sql=true // 1
spring.jpa.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect // 2
  1. 콘솔에서 쿼리 로그 확인
  2. 출력되는 쿼리 로그를 변경 (MySQL 버전)
profile
🧑🏻‍💻 Hello World!

0개의 댓글