티스토리 뷰

IT 기술

SpringBoot JPA 사용법

cheons 2022. 7. 31. 08:00
728x90
반응형

JPA(=Java Persistence API)는 자바언어로 관계형 데이터베이스를 제어할 수 있는 API입니다. 백엔드 서버 애플리케이션을 구현할 때, 구현에 빠지지 않는 내용 중 하나가 데이터베이스에 접근하여 데이터를 읽기, 삭제, 수정, 저장하는 기능입니다. JPA를 활용하면, 자바 언어로 관계형 데이터베이스를 편하게 제어할 수 있습니다. 이번 포스팅에서는 자바로 작성한 스프링 부트 애플리케이션에서 JPA를 사용하는 방법을 작성하도록 하겠습니다.

Springboot JPA 프로젝트 다운로드

https://start.spring.io/ 사이트에 접속하여, Dependency 항목을 H2 Database, Spring Data JPA를 선택하여 프로젝트를 다운로드합니다. PC에 설치되어 있는 자바 버전에 맞추어, 프로젝트의 자바 버전을 선택하시면 됩니다.

Spring JPA 실습을 위한 프로젝트 다운로드

프로젝트를 다운로드한 후, IntelliJ(이하 인텔리제이)에서  다운로드한 프로젝트를 오픈해봅니다. 프로젝트를 열면, build.gradle 파일에 있는 설정 내용에 필요한 파일을 원격 리포지토리에서 자동으로 다운되므로, 완료될 때까지 기다려줍니다. 초기 프로젝트에는 아래와 같이 DemoAPplication 이외에는 소스 파일이 없습니다. build.gradle 파일을 열어보시면 dependecy항목에 com.h2 database:h2, org.springframework.boot:spring-boot-starter-data-jpa가 추가되어 있습니다. 

dependencies {
   implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
   runtimeOnly 'com.h2database:h2'
   testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

여기까지 잘 진행되었다면, JPA를 사용할 수 있는 프로젝트 설정 및 다운로드가 완료된 것입니다.

JPA Entity 작성하기

JPA를 사용하는 실습은 Customer라는 객체를 만들고, Customer객체가 DB에 저장되는 것을 구현해보겠습니다. 아래와 같이 Customer 클래스를 작성합니다.

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Customer {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    private String firstName;
    private String lastName;

    protected Customer() {}

    public Customer(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    @Override
    public String toString() {
        return String.format(
                "Customer[id=%d, firstName='%s', lastName='%s']",
                id, firstName, lastName);
    }

    public Long getId() {
        return id;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }
}

Customer 클래스 선언부에 @Entity는 JPA의 Entity라는 것을 나타내는 것입니다. @Table가 없으면, Customer는 데이터 베이스의 테이블 이름으로 취급됩니다. @Id는 테이블의 Primary Key로 지정한다는 것입니다. @GeneratedValue는 말 그대로 자동적으로 생성되는 값이라고 지정한 것입니다. 자, 이제 Customer 클래스의 객체를 데이터베이스의 Customer 테이블에 저장해보겠습니다.

import java.util.List;
import org.springframework.data.repository.CrudRepository;

public interface CustomerRepository extends CrudRepository<Customer, Long> {

  List<Customer> findByLastName(String lastName);
  
  Customer findById(long id);
  
}

JPA에서 단순히 데이터 생성, 삭제, 수정, 읽기를 수행하려면 Repository(리포지토리) 인터페이스를 사용합니다. 아래와 같이 CustomerRepository 인터페이스를 작성하고, CrudRepository를 상속받습니다. CrudRepository의 정의를 보면, Repository 인터페이스를 상속받습니다. CrudRepository 이외에, 사용자 정의 리포지터리 인터페이스를 사용하고 싶으시면, Repository 인터페이스만 상속받아서, 필요한 함수만 정의하셔도 됩니다.

CrudRepository 인터페이스를 보면, save, findById, delete 등의 함수를 제공합니다. 하지만, findByLastName과 같은 함수는 상속받지도 않은 함수인데 어떻게 동작할까요? findByLastName과 같이 정의한 함수를 Query Method라고 부르는데요. 쿼리 메서드는 사용자가 규칙에 따라 함수명을 작성하면, JPA가 실행될 때, 쿼리문으로 변환됩니다. Spring JPA의 공식문서를 확인해보시면, Query Method를 어떻게 작성하고, 작성된 메서드가 어떻게 쿼리로 변하는지 확인할 수 있습니다.

JPA API에서 사용된 키워드 설명

Spring JPA Query Method 사용법에 관한 자세한 내용은 아래 링크를 통해 공식문서 참조 바랍니다.

 

Spring Data JPA - Reference Documentation

Example 109. Using @Transactional at query methods @Transactional(readOnly = true) interface UserRepository extends JpaRepository { List findByLastname(String lastname); @Modifying @Transactional @Query("delete from User u where u.active = false") void del

docs.spring.io

JPA로 Datbase에 접근하는 Springboot 실행하기

CommandLineRunner를 활용하여, Customer 객체를 H2 Database에 JPA를 이용하여 저장하고 읽는 예제를 구현해보겠습니다. 아래와 같이 DemoApplication을 작성합니다.

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class DemoApplication {
    private static final Logger log = LoggerFactory.getLogger(DemoApplication.class);

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

    @Bean
    public CommandLineRunner demo(CustomerRepository repository) {
        return (args) -> {
            repository.save(new Customer("Jack", "Bauer"));
            repository.save(new Customer("Chloe", "O'Brian"));
            repository.save(new Customer("Kim", "Bauer"));
            repository.save(new Customer("David", "Palmer"));
            repository.save(new Customer("Michelle", "Dessler"));

            log.info("Customers found with findAll():");
            log.info("-------------------------------");
            for (Customer customer : repository.findAll()) {
                log.info(customer.toString());
            }
            log.info("");

            Customer customer = repository.findById(1L);
            log.info("Customer found with findById(1L):");
            log.info("--------------------------------");
            log.info(customer.toString());
            log.info("");

            log.info("Customer found with findByLastName('Bauer'):");
            log.info("--------------------------------------------");
            repository.findByLastName("Bauer").forEach(bauer -> {
                log.info(bauer.toString());
            });
            for (Customer bauer : repository.findByLastName("Bauer")) {
                log.info(bauer.toString());
            }
            log.info("");
        };
    }
}
Customers found with findAll():
-------------------------------
Customer[id=1, firstName='Jack', lastName='Bauer']
Customer[id=2, firstName='Chloe', lastName='O'Brian']
Customer[id=3, firstName='Kim', lastName='Bauer']
Customer[id=4, firstName='David', lastName='Palmer']
Customer[id=5, firstName='Michelle', lastName='Dessler']

Customer found with findById(1L):
--------------------------------
Customer[id=1, firstName='Jack', lastName='Bauer']

Customer found with findByLastName('Bauer'):
--------------------------------------------
Customer[id=1, firstName='Jack', lastName='Bauer']
Customer[id=3, firstName='Kim', lastName='Bauer']
Customer[id=1, firstName='Jack', lastName='Bauer']
Customer[id=3, firstName='Kim', lastName='Bauer']

DemoApplication과 아래 실행 로그를 보면, JPA로 H2 Database에 데이터를 저장하고 조회가 된 것을 할 수 있습니다. 또한, 쿼리 메서드도 올바르게 동작하여 로그가 출력되었습니다. 

728x90
반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함