본문 바로가기
개발/SpringBoot

[SpringBoot - JPA] 스프링 부트 JPA 연동하기

by 뾰료롱 2024. 6. 20.

오늘은 "스프링 부트와 AWS로 혼자 구현하는 웹 서비스" 책의 3번째 장 JPA를 연동하고 JPA로 데이터베이스를

다뤄보도록 하겠다. 일하면서 하려니 어렵고 책 보면서 하려니 생각보다 더 어려운 거 같다..

다들 공부는 평소에 열심히 하시길...


[JPA란?]

JPA는 자바의 ORM기술을 쉽게 구현할 수 있도록 도와주는 API

여기서 ORM이란.. 아래 설명과 같다..

ORM(Objec-Relational Mapping)
:어플리케이션의 Class와 RDB(Relational DataBase)의 테이블을 매핑해주는 것으로
 기술적으로는 어플리케이션의 객체를 RDB테이블과 자동으로 영속화 해주는것

따라서 JPA를 사용하면 자바에서 객체와 데이터베이스 간의 매핑을 쉽게 처리할 수 있도록 한다.

그냥 JpaRepository를 상속하는 인터페이스에 메스드 이름만 적어놓으면 알아서

다 처리해 주는 기능이라고 한다..

한번 사용하면서 익혀보자..


[JPA 설정하기]

intelliJ에서 프로젝트 생성할 때 기본적으로 JPA를 dependencies를 추가할 수 있는데

만약 나처럼 빼먹었다면 수동으로 아래와 같이 추가해 주자

build.gradle파일에 dependencies영역에 아래 내용을 추가해 주고 gradle을 새로고침 해주면 된다.

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

 

참고용으로 현재 dependencies 내용을 추가로 넣어두니 참고하실 분은 참고해 주세요.

dependencies {   
   implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    implementation 'mysql:mysql-connector-java'
    runtimeOnly 'com.h2database:h2'
}

[JPA 사용하기]

이제 JPA를 직접 사용해 보도록 하겠습니다.

사용하기 앞서서 이전 내용에서 생성해 둔 프로젝트에 신규로 패키지를 생성하고 "Posts.java"라는

Class를 생성하도록 하겠습니다.

`

위와 같이 클래스를 생성했다면 아래 코드와 같이 입력해 주세요.

package com.example.demo2.domain.posts;

import jakarta.persistence.*;
import lombok.Builder;
import lombok.NoArgsConstructor;
import org.hibernate.Length;

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

    /*코드설명
     * @Entity
     * :테이블과 링크될 클래스임을 나타냅니다. (기본값으로 클래스의 카멜케이스 이름을 언더스코어 네이밍(_)으로 테이블이름을 매핑)
     *
     * @Id
     * :해당 테이블의 PK필드를 나타냅니다.
     *
     * @GeneratedValue
     * :PK생성 규칙을 나타냅니다.
     *
     * @Column
     * :테이블의 컬럼을 나타내며 굳이 선언하지않아도 해당 클래스의 필드는 모두 컬럼이 됩니다.
     *
     * @
     * */
}

 

위와 같이 코드를 작성해 주셨다면 위에서 생성한 Posts클래스를 Database에 접근하기 위해서

위에 생성했던 domain.posts패키지에 "PostsRepository.java"

Interface를 생성해 줍니다. 생성하고 extend를 아래와 같이 해줍시다.

 

package com.example.demo2.domain.posts;

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

public interface PostsRepository extends JpaRepository<Posts, Long> {
}

 

[테스트코드 작성]

위 내용과 같이 Posts라는 클래스를 생성하고 PostsRepository 인터페이스를 생성해 주었다면 아래와 같이

테스트 코드를 작성하여 검증해 보도록 합니다.

package com.example.demo2.domain.posts;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;

@ExtendWith(SpringExtension.class)
@SpringBootTest
public class PostsRepositoryTest {

    @Autowired
    PostsRepository postsRepository;

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

    @Test
    public void load() {
        String title = "TEST";
        String content ="TEST1111";



        postsRepository.save(Posts.builder()
                .title(title)
                .content(content)
                .author("123@123")
                .build());

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

        Posts posts = postsList.get(0);
        assertThat(posts.getTitle()).isEqualTo(title);
        assertThat(posts.getContent()).isEqualTo(content);

    }

    /*코드설명
    * @AfterEach
    * : 기존의 @After 어노테이션과 동일한 기능을 하며, Junit에서 단위 테스트가 끝날때마다 수행되는 메소드를 지정해준다
    *
    * postsRepository.save
    * : 테이블 posts에 insert/update 쿼리를 실행해준다.
    *   id값이 있다면 update 없다면 insert 쿼리를 실행한다.
    *
    * postsRepository.findAll()
    * : 테이블의 모든 데이터를 조회해오는 메소드
    * */
}

위 코드를 작성하였다면, load 메서드 옆에 화살표를 눌러 실행해 봅시다.

실행했때 아래 이미지와 같이 성공했다고 표시되면 테스트는 완료되었습니다.

이렇게 테스트가 완료된 걸 확인할 수도 있지만 직접적으로 JPA를 통해 쿼리가 실행되는걸

콘솔에서 확인할수 있는 방법이 있습니다.

application.properties 파일에 아래 이미지처럼 코드 두줄을 추가해 주시면 됩니다.

spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

 

입력 완료하였다면 다시 테스트 코드에서 load() 메서드를 실행해 보겠습니다.

실행하게 되면 아래 이미지와 같이 콘솔에 쿼리문이 출력되는 걸 확인할 수 있습니다.

 


[후기]

생각보다 테스트코드 작성하는 게 쉽지 않았다.

책이 옛날 거다 보니 SpringBoot의 버전이 차이가 많이 나다 보니 어노테이션 defendencie 등이

달라진 것들이 많아서 오류를 해결한다고 좀 많이 힘들었다..

생각보다 진도가 느려서 걱정이지만 파이팅............!