TIL 5 | Spring Data JPA 적용하기

softpeter·2021년 8월 31일
0
post-thumbnail

프로젝트에 Spring Data Jpa 적용하기

build.gradle 의존성 등록

  • org.springframework.boot:spring-boot-starter-data-jpa
  • com.h2database:h2
buildscript {
    ext {
        springBootVersion = '2.1.7.RELEASE'
    }

    repositories {
        mavenCentral()
        jcenter()
    }

    dependencies {
//    처음 생성하면 나오던 코드
//    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
//    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin:   'java'
apply plugin:   'eclipse'
apply plugin:   'org.springframework.boot'
apply plugin:   'io.spring.dependency-management'

group 'com.coocon.scraping'
version '1.0.0-SNAPSHOT-' + new Date().format("yyyyMMddHHmmss")

repositories {
    mavenCentral()
    jcenter()
}

dependencies {
    implementation 'org.testng:testng:7.1.0'
    compile('org.springframework.boot:spring-boot-starter-web')
    compile('org.projectlombok:lombok')
    testCompile "org.projectlombok:lombok"
    annotationProcessor('org.projectlombok:lombok')
    testAnnotationProcessor('org.projectlombok:lombok')
    // Spring DATA JPA 적용하기
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('com.h2database:h2')
//    testCompile "junit:junit:4.12"
    testCompile('org.springframework.boot:spring-boot-starter-test')


}
  1. spring-boot-starter-data-jpa
    • 스프링 부트용 Spring Data Jpa 추상화 라이브러리
    • 스프링 부트 버전에 맞춰 자동으로 JPA관련 라이브러리들의 버전을 관리
  2. h2
    • 인메모리 관계형 데이터베이스
    • 별도의 설치가 필요없이 프로젝트 의존성만으로 관리 가능
    • 메모리에서 실행되기 때문에 애플리케이션을 재시작할 때마다 초기화된다는 점을 이용하여 테스트 용도로 많이 사용

domain 패키지 생성

  • 도메인을 담을 패키지
  • 도메인이란?
    • 게시글, 댓글, 회원, 정산, 결제 등 소프트웨어에 대한 요구사항 혹은 문제 영역

posts 패키지, Posts 클래스 생성

  • domain 패키지에 생성

Posts 클래스의 Code

package scraping.coocon.com.domain.posts;

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

import javax.persistence.*;

@Getter
@NoArgsConstructor
@Entity
public class Posts {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(length = 500, nullable = false)
    private String title;

    @Column(columnDefinition = "TEXT", nullable = false)
    private String content;

    private String author;

    @Builder
    public Posts(String title, String content, String author) {
        this.title = title;
        this.content = content;
        this.author = author;
    }
}
  • Posts 클래스는 실제 DB의 테이블과 매칭될 클래스

  • 보통 Entity 클래스라고 부름

  • JPA를 사용하면 DB 데이터에 작업할 경우, Entity 클래스의 수정을 통해 작업

  • @Entity

    • 테이블과 링크될 클래스임을 나타냄
    • 기본값으로 클래시의 카멜케이스 이름을 언더스코어 네이밍 으로 테이블 이름을 매칭
  • @Id

    • 해당 테이블의 PK 필드
  • @GeneratedValue

    • PK의 생성 규칙을 나타냄
    • 스프링 부트 2.0에서는 GenerationType.IDENTITY 옵션을 추가해야만 auto_increment가 됨
  • Column

    • 테이블의 칼럼을 나타냄
    • 굳이 선언하지 않더라도 해당 클래스의 필드는 모두 칼럼이 됨
    • 사용하는 이유는, 기본 값 외에 추가로 변경이 필요한 옵션이 있으면 사용
      • EX) 문자열의 경우 VARCHAR(255)가 기본값인데, 사이즈를 500으로 늘릴 때 사용
      • EX) 타입을 TEXT로 변경할 때 사용
  • @NoArgsConstructor

    • 기본 생성자 자동 추가
    • public Posts(){}와 같은 효과
  • @Getter

    • 클래스 내 모든 필드의 Getter 메소드를 자동 생성
  • @Builder

    • 해당 클래스의 빌더 패턴 클래스를 생성
    • 생성자 상단에 선언 시 생성자에 포함된 필드만 빌더에 포함

JpaRepository 생성

package scraping.coocon.com.domain.posts;

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

public interface PostsRepository extends JpaRepository<Posts, Long> {
}
  • DB Layer 접근자이며, JPA에선 Repository 라고 부르며 인터페이스 로 생성
  • 단순히 인터페이스를 생성 후, JpaRepository<Entity 클래스, PK 타입>을 상속하면 기본적인 CRUD 메소드가 자동으로 생성 됨
  • @Repository 를 추가할 필요도 없음
  • Entity 클래스와 기본 Entity Repository는 함께 위치해야 함

Spring Data JPA 테스트 코드 작성

  • test 디렉토리에 domain.posts 패키지 생성, PostsRepositoryTest 클래스 생성
package scraping.coocon.com.web.domain.posts;

import javafx.beans.binding.BooleanExpression;
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 scraping.coocon.com.domain.posts.Posts;
import scraping.coocon.com.domain.posts.PostsRepository;

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

import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest
public class PostsRepositoryTest {

    @Autowired
    PostsRepository postsRepository;

    @After
    public void cleanup() {
        postsRepository.deleteAll();
    }

    @Test
    public void 게시글저장_불러오기() {
        //given
        String title = "테스트 게시글";
        String content = "테스트 본문";

        postsRepository.save(Posts.builder().title(title)
                                            .content(content)
                                            .author("goodzlmn@naver.com")
                                            .build());

        //when
        List<Posts> postsList = postsRepository.findAll();

        //then
        Posts posts = postsList.get(0);
        assertThat(posts.getTitle()).isEqualTo(title);
        assertThat(posts.getContent()).isEqualTo(content);
    }
}
  • @After
    • Junit에서 단위 테스트가 끝날 때마다 수행되는 메소드를 지정
    • 보통은 배포 전 전체 테스트를 수행할 때 테스트간 데이터 침범을 막기 위해 사용
  • postsRepository.save
    • 테이블 posts에 insert/update 쿼리를 실행
    • id 값이 있다면 update
    • id 값이 없다면 insert
  • postsRepository.findAll
    • 테이블 posts에 있는 모든 데이터를 조회하는 메소드
  • 별다른 설정 없이 @SpringBootTest 를 사용할 경우 H2 데이터베이스를 자동으로 실행해줌

실제로 실행된 쿼리 형태 보기

  • application.properties 파일 생성 및 설정
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect

profile
dev.Back-end | Aal izz well

0개의 댓글

관련 채용 정보