본문 바로가기
Apache Avro

Spring Boot REST API 및 DB 연동 실습 - 2 (JPA)

by 자는게젤루좋아 2024. 9. 28.

 

이젠 본격적으로 JPA 환경설정을 수정해봅니다.

기존의 pom.xml에 jpa 및 postgresql 사용을 위한 다음의 dependency들을 추가 합니다.

 

pom.xml

<!-- JPA 의존성 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<!-- PostgreSQL 의존성 -->
<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
</dependency>

 

application.yml

mvn clean install 명령어를 수행 후, application.yml에 다음 내용들을 추가합니다.

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/${dbName}
    username: ***********
    password: ***********
    driver-class-name: org.postgresql.Driver
  jpa:
    hibernate:
      ddl-auto: update  # 테이블 자동 생성 및 업데이트
    show-sql: true      # 실행되는 SQL 쿼리 출력
    properties:
      hibernate:
        dialect: org.hibernate.dialect.PostgreSQLDialect

 

여기서, ddl-auto에 대해 아래에서 좀 더 내용을 살펴보도록 하겠습니다.


ddl-auto 옵션

spring.jpa.hibernate.ddl-auto는 JPA에서 데이터베이스 스키마 관리를 제어하는 설정 옵션으로,

Hibernate가 데이터베이스 테이블을 어떻게 생성하고 업데이트할지를 결정합니다.

이 옵션에는 다양한 값이 있으며, 각 값은 특정한 동작을 수행합니다.

ddl-auto의 주요 옵션 종류

  1. none
    • Hibernate가 데이터베이스 스키마에 대한 어떠한 작업도 수행하지 않습니다. 즉, 애플리케이션이 실행될 때 테이블을 생성하거나 수정하지 않으며, 사용자가 수동으로 스키마를 관리해야 합니다.
  2. validate
    • 데이터베이스에 이미 존재하는 테이블과 JPA 엔티티 간의 매핑이 일치하는지 검증만 합니다. 데이터베이스를 변경하거나 수정하지 않으며, 매핑이 일치하지 않으면 애플리케이션이 실행되지 않습니다.
  3. update
    • 데이터베이스에 없는 테이블이나 컬럼을 자동으로 추가하지만, 기존 데이터는 삭제하지 않습니다. 애플리케이션이 실행될 때마다 엔티티 클래스와 매핑된 대로 데이터베이스 구조를 업데이트합니다.
  4. create
    • 애플리케이션이 실행될 때마다 데이터베이스의 기존 테이블을 삭제하고, 엔티티에 따라 새로 테이블을 생성합니다. 기존 데이터는 모두 사라지므로, 주의해서 사용해야 합니다.
  5. create-drop
    • create와 동일하게 애플리케이션이 실행될 때 테이블을 생성하지만, 애플리케이션이 종료될 때 테이블을 삭제합니다. 테스트 환경에서 유용할 수 있습니다.
  6. create-only (Hibernate 6에서 도입)
    • 애플리케이션이 실행될 때 데이터베이스 스키마를 처음 한 번 생성하고, 이후로는 유지합니다. 기존의 테이블을 변경하거나 업데이트하지 않고, 단지 생성만 합니다.

요약

  • 테스트용: create, create-drop
  • 개발용: update
  • 운영/프로덕션 환경: validate, none (스키마는 수동 관리)

프로덕션 환경에서는 데이터 손실 위험이 있는 create, update는 피하고, validate나 none을 주로 사용해 수동으로 스키마를 관리하는 것이 권장됩니다.


우리는 테스트/개발용 이기에, create-drop 및 update 설정을 실행해보도록 하겠습니다.

 

1. create-drop으로 설정

  • create와 동일하게 애플리케이션이 실행될 때 테이블을 생성하지만, 애플리케이션이 종료될 때 테이블을 삭제합니다. 테스트 환경에서 유용할 수 있습니다.
  • 이 설정을 이용하여 test_users 테이블 생성 뒤, id, name, email 컬럼 생성 후 특정 값을 insert 해보도록 하겠습니다.
  • 이 조건에 의하면, 서버 compile 시 test_users 테이블 생성 후 -> stop 시, test_users 테이블이 drop 됩니다.

application.yml

yml 파일에 있는 ddl-auto를 create-drop으로 변경해보도록 하겠습니다.

jpa:
  hibernate:
    #ddl-auto: update
    ddl-auto: create-drop

 

User.java

Table name에 test_users를 지정하고 id, name, email 객체를 생성하고 getter & setter를 생성합니다.

이 때, id는 시퀀스 값처럼 자동으로 증가하는 값이기 때문에, 따로 설정하지 않아도 됩니다. (시작 넘버 : 1)

package com.example.my_rest_api.model;

import jakarta.persistence.*;

@Entity
@Table(name = "test_users")
public class User {

    // primary key 설정을 하지 않으면 실행시 에러가 발생합니다.
    @Id
    // id 는 자동으로 1씩 증가됩니다. (start : 1)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    private String email;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

 

RestService.java

이제 User 객체를 가져와 데이터들을 등록합니다.

@Autowired
private UserRepository userRepository;

@PostConstruct
public void init() {
    // 애플리케이션이 시작될 때 샘플 데이터 추가
    User user = new User();
    user.setName("Sarah");
    user.setEmail("sarah@example.com");
    userRepository.save(user);

    System.out.println("User saved: " + user);
}

 

UserRepository.java

UserRepository 인터페이스를 지정해 JpaRepository 를 상속받습니다. 

package com.example.my_rest_api.repository;

import com.example.my_rest_api.model.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
}

 

이 때, JpaRepository에서 User, Long을 파라미터로 넣는 이유는,

JpaRepository class가 다음 코드를 지니고 있기 때문입니다.

// T는 GenericType, ID는 아까 우리가 선정한 id 값이라고 볼 수 있습니다.
public interface JpaRepository<T, ID>

 

- DB 변경 내역 확인

test_users 테이블이 생성됨

 

insert한 데이터가 정상적으로 조회됨

 

서버를 중지하면, 다음과 같이 Table이 제거된 것을 확인할 수 있습니다.

RestService.java

이해를 돕기 위해, User에 1명을 더 추가해보도록 하겠습니다.

@PostConstruct
public void init() {
    // 애플리케이션이 시작될 때 샘플 데이터 추가
    User user = new User();
    user.setName("Sarah");
    user.setEmail("sarah@example.com");
    userRepository.save(user);
    
    // 한명 더 추가합니다.
    User user2 = new User();
    user2.setName("Tom");
    user2.setEmail("tom@example.com");
    userRepository.save(user);

    System.out.println("User saved: " + user);
}

 

DB 변경 내역

확인해 보면, 이전의 데이터는 제거 되고, 2개의 row가 나오는 것을 확인할 수 있습니다.

서버를 재시작하면, 다음과 같이 결과가 나타난다.

 

2. update으로 설정

  • 데이터베이스에 없는 테이블이나 컬럼을 자동으로 추가하지만, 기존 데이터는 삭제하지 않습니다. 애플리케이션이 실행될 때마다 엔티티 클래스와 매핑된 대로 데이터베이스 구조를 업데이트합니다.
  • 이 설정을 이용하여 test_users 테이블 생성 뒤, id, name, email 컬럼 생성 후 특정 값을 insert 후, update 해보도록 하겠습니다.
  • 이 조건에 의하면, 서버 compile 시 test_users 테이블 생성 후 -> stop이 되어도 데이터가 날라가지 않습니다.

 

application.yml

yml 파일에 있는 ddl-auto를 update로 변경해보도록 하겠습니다.

jpa:
  hibernate:
    ddl-auto: update
    #ddl-auto: create-drop

 

나머지 소스는 동일하게 구성한 뒤, compile 해보도록 하겠습니다.

 

DB 변경 내역

확인해 보면, 2개의 row가 나오는 것을 확인할 수 있습니다.

서버를 시작하면, 2개의 row가 추가되어 있습니다.

 

한 번더, compile 해보도록 하겠습니다.

데이터가 drop & insert 가 아닌, update 되기때문에, 4개의 row를 조회할 수 있습니다.

서버를 재시작하면 4개의 row를 확인할 수 있습니다.

 

 

다음 시간엔 avro type의 데이터를 table에 insert 해보도록 하겠습니다.


(참고용) 일반적인 디렉토리 구조

Spring boot 프로젝트의 일반적인 디렉토리 구조

 

댓글