JPA - 기본 설정

최상민·2023년 11월 27일
1

Spring Boot

목록 보기
3/5

자바 웹 개발 워크북 - 예스24
아래내용은 ‘자바 웹 개발 워크북(구멍가게 코딩단)’ 책의 pp. 432 ~ 508 (5.3. Spring Data JPA ~ 5.4. 게시물 관리 완성하기)의 내용을 토대로 작성되었습니다.

JPA 🔗

JPA(Java Persistence API)는 자바 플랫폼에서 객체 관계 매핑(ORM, Object-Relational Mapping)을 위한 표준 인터페이스 API로, 프레임워크이다. JPA는 객체 지향 언어인 자바로 관계형 데이터베이스를 다룰 때, SQL 쿼리 대신 객체를 사용해 데이터베이스와 상호 작용할 수 있도록 도와준다. JPA 구현체에는 Hibernate, EclipseLink, Apache OpenJPA 등이 있다.

JPA 기본 설정

JPA 라이브러리 설정

  • build.gradle
    buildscript {
        ext {
            queryDslVersion = "5.0.0"
        }
    }
    
    plugins {
        id "java"
        id "war"
        id "org.springframework.boot" version "2.7.17"
        id "io.spring.dependency-management" version "1.0.15.RELEASE"
    }
    
    group = "com.example"
    version = "0.0.1-SNAPSHOT"
    
    java {
        sourceCompatibility = "17"
    }
    
    configurations {
        compileOnly {
            extendsFrom annotationProcessor
        }
    }
    
    repositories {
        mavenCentral()
    }
    
    dependencies {
        implementation "org.springframework.boot:spring-boot-starter-data-jpa"
        implementation "org.springframework.boot:spring-boot-starter-thymeleaf"
        implementation "org.springframework.boot:spring-boot-starter-web"
    
        // querydsl 라이브러리
        implementation "com.querydsl:querydsl-jpa"
        implementation "com.querydsl:querydsl-apt"
        implementation "com.querydsl:querydsl-core"
        implementation "com.querydsl:querydsl-sql"
    
        // modelMapper: DTO와 엔티티 간 변환 처리해주는 라이브러리
        implementation "org.modelmapper:modelmapper:3.1.0"
    
        // 타임리프로 LocalDateTime format 을 temporals 로 맞추기 위해 필요
        implementation "org.thymeleaf.extras:thymeleaf-extras-java8time3"
    
        compileOnly("org.projectlombok:lombok", "com.querydsl:querydsl-apt:${queryDslVersion}:jpa")
        developmentOnly "org.springframework.boot:spring-boot-devtools"
        runtimeOnly "org.mariadb.jdbc:mariadb-java-client"
    
        // 기존 롬복 이외도, javax 와 querydsl 어노테이션 추가
        annotationProcessor(
                "org.projectlombok:lombok",
                "javax.persistence:javax.persistence-api",
                "javax.annotation:javax.annotation-api",
                "com.querydsl:querydsl-apt:${queryDslVersion}:jpa");
    
        providedRuntime "org.springframework.boot:spring-boot-starter-tomcat"
    
        testImplementation "org.springframework.boot:spring-boot-starter-test"
    
        // test junit 시에 lombok 추가
        testCompileOnly "org.projectlombok:lombok"
        testAnnotationProcessor "org.projectlombok:lombok"
    }
    
    tasks.named("bootBuildImage") {
        builder = "paketobuildpacks/builder-jammy-base:latest"
    }
    
    tasks.named("test") {
        useJUnitPlatform()
    }
    
    sourceSets {
        main.java.srcDirs = ["$projectDir/src/main/java", "$projectDir/build/generated"]
    }

💡 왜 그런지 모르겠는데 $projectDir 등의 gradle의 변수를 쓰려면 ‘작은 따옴표’는 안된다. “큰 따옴표”안에 써야 한다.

Spring Boot 3.0 이상 JPA 설정

참고한 블로그: Spring Boot 3.0 이상 시 QueryDSL 설정

  • build.gradle
buildscript {
    ext {
        queryDslVersion = "5.0.0"
    }
}


plugins {
    id 'java'
    id 'war'
    id 'org.springframework.boot' version '3.1.6'
    id 'io.spring.dependency-management' version '1.1.4'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
    sourceCompatibility = '17'
}

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    // 기본 라이브러리 ( spring initializer 로 추가하기)
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    // implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-websocket'


    // querydsl 라이브러리
    implementation "com.querydsl:querydsl-jpa:${queryDslVersion}:jakarta" // 기존에는 그냥 jpa, 3 버전 이상은 :jakarta 추가
    implementation "com.querydsl:querydsl-apt:${queryDslVersion}:jakarta"
    // apt(annotation processing tool), Q도메인 생성. 컴파일 시에만 사용됨
    implementation "com.querydsl:querydsl-core"
    implementation "com.querydsl:querydsl-sql"

    // modelMapper: DTO 와 엔티티 간 변환 처리해주는 라이브러리
    implementation "org.modelmapper:modelmapper"

    compileOnly("org.projectlombok:lombok", "com.querydsl:querydsl-apt:${queryDslVersion}:jakarta") // 롬복 외에도 querydsl 어노테이션 추가

    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'

    // 기존 롬복 이외도, jakarta 와 querydsl 어노테이션 추가 (spring boot 3.0 이상은 jakarta 대신 jakarta 사용)
    annotationProcessor(
            "org.projectlombok:lombok",
            "jakarta.persistence:jakarta.persistence-api",
            "jakarta.annotation:jakarta.annotation-api",
            "com.querydsl:querydsl-apt:${queryDslVersion}:jakarta"); // querydsl-apt:jpa -> querydsl-apt:jakarta


    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.security:spring-security-test'
}

tasks.named('bootBuildImage') {
    builder = 'paketobuildpacks/builder-jammy-base:latest'
}

tasks.named('test') {
    useJUnitPlatform()
}

// 프로젝트의 소스 코드 및 리소스 디렉토리 구성
// 개발 시 작성하는 java 파일의 위치 (src/main/java)와 Q도메인이 저장되는 위치(build/generated)를 명시
// 기존 파일과 Q도메인이 gradle 빌드 시 자동 컴파일 되게 함
sourceSets {
    main.java.srcDirs = ["$projectDir/src/main/java", "$projectDir/build/generated"]
}

JPA application 설정

application.properties에 다음과 같이 설정해주어야 한다.

  • spring.jpa.hibernate.ddl-auto: 엔티티 객체를 만들면 알아서 엔티티에 해당하는 테이블이 만들어진다.
    • create: 새로운 테이블 만듦
      ex) board, board1, board2 …
    • createdrop: board를 지우고 새로 만든다.
    • none: 수동으로 테이블 만들어야 함
    • update: 현재 테이블 있으면 만들지 말고 데이터 누적. 테이블이 없으면 새로 만든다. (많이 사용함) 시작시, 도메인과 스키마 비교하여 필요한 컬럼 추가 등의 작업 실행. 데이터는 삭제하지 않음.
    • validate: 기존과 새로운 것의 달라진 내용만 표시해줌. 스키마가 적합한지 검사함. 문제가 있으면 예외 발생.
  • spring.jpa.properties.hibernate.format_sql: Hibernate 실행 시 SQL 쿼리를 개행, 들여쓰기 등을 사용해 보기 쉽게 바꿔줌
  • spring.jpa.show-sql: JPA(Hibernate) 실행 시 해당 SQL 쿼리를 콘솔에 출력
  • spring.jpa.hibernate.naming.physical-strategy: 엔티티 클래스의 카멜케이스 필드명을 데이터베이스의 스네이크 케이스 컬럼명으로 자동 매핑해줌.
server.port=8080
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.url=jdbc:mariadb://localhost:3306/springData
spring.datasource.username=root
spring.datasource.password=1234

logging.level.org.springframework=info
logging.level.com.shop=debug

spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.show-sql=true
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

spring.servlet.multipart.enabled=true
spring.servlet.multipart.location=C:\\upload
spring.servlet.multipart.max-request-size=30MB
spring.servlet.multipart.max-file-size=10MB

com.springData.upload.path=C:\\upload

JPA Run Configuration

JPQL에서 Q도메인이 중복 build되어 오류가 발생하는 것을 방지한다.

  1. Run 표시가 있는 부분에서 더보기 버튼을 눌러 Cofiguration - Edit으로 들어간다.
    Run 표시가 있는 부분에서 더보기 버튼을 눌러 Cofiguration - Edit으로 들어간다.
  2. Edit Configuration Settings에서 Modify Options - Add Before launch task를 누른다.
    Edit Configuration Settings에서 Modify Options - Add Before launch task를 누른다.
  3. Run Gradle task 선택
    Run Gradle task 선택
  4. 폴더 버튼을 눌러 gradle project를 이 프로젝트로 설정하고, Tasks에 “clean”을 입력한다. 그후 Ok, Apply를 눌러 변경된 설정을 적용한다.
    폴더 버튼을 눌러 gradle project를 이 프로젝트로 설정하고, Tasks에 “clean”을 입력한다. 그후 Ok, Apply를 눌러 변경된 설정을 적용한다.

위의 설정을 하지 않는다면 build를 하기 전에 반드시 터미널에 아래 코드를 입력한다.

./gradlew clean

객체 매핑

  • @Entity: 테이블과 매핑되는 자바의 객체 클래스
  • @Table: 엔티티 클래스와 매핑할 테이블 정보
  • @Id: 테이블 클래스의 필드(식별자 필드)를 기본 키(Primary Key)에 매핑.
  • @Column: 필드를 컬럼에 매핑
  • 어노테이션이 없는 경우: 필드명이 컬럼명과 매핑됨. 대소문자를 구분하는 데이터베이스의 경우, @Column 을 사용해야 대소문자를 신경쓰지 않을 수 있다.
  • @GeneratedValue: 해당 컬럼의 값 생성 전략으로, 주로 PK(기본키)를 생성하는데 사용된다.
    • Identity: 데이터베이스가 자동 생성하도록 하는 것. MySQL 또는 MariaDB에서 AUTO_INCREMENT와 같다.
    • SEQUENCE: 데이터베이스의 시퀀스 오브젝트를 사용(OACLE) - @SequenceGenerator 필요
    • TABLE: 키생성용 테이블 사용. 모든 DB에서 사용 - @TableGenerator필요
    • AUTO: 각 데이터베이스의 방식에 따라 자동 지정. 기본값이다.
package com.shop.domain;

import lombok.*;

import javax.persistence.*;

@Entity
public class Board {
// 공통 속성이 들어가는 경우 public class Board extends BaseEntity로 바꿔주어야 한다.
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long bno;

    @Column(length = 500, nullable = false) //컬럼의 길이와 null허용여부
    private String title;

    @Column(length = 2000, nullable = false)
    private String content;

    @Column(length = 50, nullable = false)
    private String writer;
}

공통 속성 처리 BaseEntity

기존의 클래스는 BaseEntity 클래스를 상속하도록 변경한다.

  • Board extends BaseEntity
    package com.shop.domain;
    
    import lombok.*;
    
    import javax.persistence.*;
    
    @Entity
    @Getter
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @ToString
    public class Board extends BaseEntity{
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long bno;
    
        @Column(length = 500, nullable = false) //컬럼의 길이와 null허용여부
        private String title;
    
        @Column(length = 2000, nullable = false)
        private String content;
    
        @Column(length = 50, nullable = false)
        private String writer;
    
        public void change(String title, String content){
            this.title = title;
            this.content = content;
        }
    
    }
  • @MappedSuperclass: 특정 클래스를 엔티티 클래스의 부모 클래스로 지정
  • @EntityListeners(value = {AuditingEntityListener.class}): 엔티티가 데이터베이스에 추가되거나 변경될 때 자동으로 시간 값을 지정한다. 이를 활성화하기 위해서는 프로젝트 설정에 @EnableJpaAudititng을 추가해야 한다.
  • @CreatedDate: 엔티티가 최초로 생성될 때 일시 기록
  • @LastModifiedDate: 엔티티가 업데이트될 때마다의 시간 정보 저장
package com.shop.domain;

import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;

@MappedSuperclass
@EntityListeners(value = { AuditingEntityListener.class })
@Getter
abstract class BaseEntity {

    @CreatedDate
    @Column(name = "regdate", updatable = false)
    private LocalDateTime regDate;

    @LastModifiedDate
    @Column(name ="moddate" )
    private LocalDateTime modDate;

}
  • EnableJpaAuditing: [src - main - java - 홈페이지]에 있는 프로젝트 이름의 자바파일, 즉 프로젝트 설정에 이 어노테이션을 추가한다.
package com.shop;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@SpringBootApplication
@EnableJpaAuditing
public class B01Application {

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

}
profile
상민

0개의 댓글