[JPA] JPA 세팅하기 - Spring Data JPA

koline·2024년 1월 8일

JPA

목록 보기
2/11

스프링 부트에 Spring Data JPA라이브러리를 사용하여 JPA를 세팅하는 방법을 알아보자.

개발환경
Spring Boot: 3.2.0-SNAPSHOT
Gradle: gradle-8.4
Java: OpenJDK17

1. build.gradle에 JPA dependency 추가하기

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

2. application.properties에 JPA 설정 추가하기

# 아래 데이터 추가
logging.level.org.hibernate.SQL=DEBUG
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.format_sql=true

만약 application.properties가 아닌 yml이나 xml 파일을 사용한다면 해당 파일의 형식만 맞춰주면 된다.

옵션을 하나하나 살펴보자면

logging.level.org.hibernate.SQL

Logger에서 SQL 쿼리문을 출력할 로그 레벨을 나타낸다.

TRACE < DEBUG < INFO < WARN < ERROR

위 순서대로 중요도가 높다.

spring.jpa.show-sql

로그로 실행되는 쿼리문을 출력할지 여부를 나타낸다.

default는 false

spring.jpa.hibernate.ddl-auto

DDL (Data Definition Language, 데이터 정의어)를 자동생성할지 여부를 나타낸다.

@Entity, @Table, @Column 등 데이터의 정의를 나타내는 어노테이션이 붙은 객체와 속성에 대한 DDL 쿼리를 빌드시에 자동으로 생성 시킬지 여부이다.

기본적으로 @Entity 어노테이션에 name 속성이 없다면 class명으로 생성되고 Entity명을 다르게 주고 싶다면 name 속성을 준다.

만약 Entity 명과 DB에 들어가는 Table명을 다르게 설정하고 싶다면 @Table어노테이션을 사용해 name 속성을 줌으로써 설정할 수 있다. (아래 3번 참고)

종류는 다음과 같다.

  • create
    엔티티로 등록된 클래스와 매핑되는 테이블을 자동으로 생성한다. 기존에 해당 클래스와 매핑되는 테이블이 존재한다면 기존 테이블을 삭제하고 테이블을 생성한다.

  • create-drop
    엔티티로 등록된 클래스와 매핑되는 테이블이 존재한다면 기존 테이블을 삭제하고 자동으로 테이블을 생성해주는 것은 똑같지만, 애플리케이션이 종료될 때 테이블을 삭제한다.

  • update
    엔티티로 등록된 클래스와 매핑되는 테이블이 없으면 새로 생성하는 것은 동일하지만 기존 테이블이 존재한다면 위의 두 경우와 달리 테이블의 컬럼을 변경하게 된다.

    주의할 점은 update의 경우 테이블과 칼럼은 자동으로 수정 되지만 속성의 경우 update 되지 않을 수 있다.

  • validate
    DDL을 작성하여 테이블을 생성하거나 수정하지 않고, 엔티티 클래스와 테이블이 정상적으로 매핑되는지만 검사한다. 만약 테이블이 아예 존재하지 않거나, 테이블에 엔티티의 필드에 매핑되는 컬럼이 존재하지 않으면 예외를 발생시키면서 애플리케이션을 종료한다.

  • none(default)
    DDL 자동 생성 안함

이 기능은 개발을 용이하게 하기 위함이기 때문에 개발환경에서만 사용하고 실제 운영서버의 경우 주의해서 사용할 필요가 있다. 운영환경에서는 validate 또는 none으로 설정하는 것이 좋다.

spring.jpa.properties.hibernate.format_sql

쿼리를 formatting할 지 여부를 나타낸다.

만약 false로 설정되면 쿼리는 한줄로 로그에 표시되고 true로 설정되면 보기 예쁘게 줄바꿈되어 나온다.

3. Entity 생성

// /com/practice/project/test/entity/TestEntity.java
package com.practice.project.test.entity;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import lombok.*;

@Builder
@Entity(name = "test_entity")
public class TestEntity {

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

    @Column
    private String val1;

    @Column
    private String val2;
}

4. Repository 생성

// /com/practice/project/test/repository/TestRepository.java
package com.practice.project.test.repository;

import com.practice.project.test.entity.TestEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

// JpaRepository를 상속하여 사용. <객체, ID타입>
@Repository
public interface TestRepository extends JpaRepository<TestEntity, Long> {
}

이렇게 설정하면 JpaRepository에서 제공하는 기본 적인 쿼리와 쿼리 양식을 사용할 수 있다.

5. Controller 생성

// /com/practice/project/test/controller/TestController.java
package com.practice.project.test.controller;

import com.practice.project.test.repository.TestRepository;
import com.practice.project.test.entity.TestEntity;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import java.util.List;

// JpaRepository를 상속하여 repository (interface) 생성. <객체, ID타입>
@RestController
@RequiredArgsConstructor
public class TestController {

	// 여기서는 서비스까지 생성하기는 귀찮아서 repository를 그대로 사용했지만
    // 실제로는 이렇게 사용하면 안된다.
    // 3-tier 구조를 지켜야한다!
	private final TestRepository testRepository;

	@PostMapping("/test")
    public ResponseEntity<TestEntity> createTest() {
    	TestEntity testEntity = testRepository.save(
        	TestEntity.builder()
        		.val1("val1")
                .val2("val2")
            .build()
        );
        
		return ResponseEntity.ok(testEntity);
    }
    
    @GetMapping("/tests")
    @ResponseStatus(HttpStatus.OK)
    public List<TestEntity> getTestList() {
    	return testRepository.findAll();
    }
}
profile
개발공부를해보자

0개의 댓글