개발이 취미인 사람

[JPA] - Entity 정의 방법 본문

백앤드(Back-End)/Jpa

[JPA] - Entity 정의 방법

RyanSin 2024. 12. 14. 14:23
반응형

개요

안녕하세요. 이번 시간에는 Jpa에서 Entity를 정의하는 방법에 대해 알아보겠습니다.

 

혹시 지난 시간에 내용을 학습하고 오시지 못하신 분들은 아래 링크를 통해 학습하고 오시는 걸 추천드리겠습니다.

[JPA] - 영속성 컨텍스트(2)

 

[JPA] - 영속성 컨텍스트(2)

개요안녕하세요. 이번 시간에는 JPA에서 조회 및 쓰기 그리고 수정 동작에 대해 알아보겠습니다. 1차 캐시, 쓰기 저장소, 변경 감지에 대한 개념에 대해서도 같이 설명하겠습니다. 혹시 지난 시

any-ting.tistory.com

 

 

JPA는 Java Persistence API의 약자이며, 자바 애플리케이션에서 객체와 관계형 데이터베이스 간의 맵핑을 관리해주는 기술입니다.

 

개발자가 SQL을 직접 작성하지 않고도 데이터베이스와 상호작용할 수 있도록 해주는 ORM 기술의 일종입니다.

 

가장 기초가 되는 부분은 자바 클래스와 관계형 데이터베이스를 연결하는 Entity에 대해서 정의하는 방법에 대해 알아보겠습니다.

 

JPA Entity란?

Entity는 데이터베이스 테이블에 매핑되는 클래스입니다. JPA에서는 @Entity 어노테이션을 사용하여 클래스가 Entity임을 선언합니다. 데이터베이스 테이블의 스키마와 클래스의 속성 간 매핑을 통해 객체 지향적인 방식으로 데이터를 관리할 수 있습니다.

 

데이터베이스에서 member라는 테이블을 연결할 때 아래와 같이 작성할 수 있습니다.

package com.ryan.kotlinspirngjpa.jpa.entity

import jakarta.persistence.*
import org.hibernate.annotations.SQLDelete
import org.hibernate.annotations.SQLRestriction

@Entity
@Table(name = "member")
@SQLDelete(sql = "UPDATE member SET deleted_at = CURRENT_TIMESTAMP WHERE id = ?")
@SQLRestriction("deleted_at is NULL")
class MemberEntity(
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long? = null,

    @Column(name = "name", nullable = false, unique = true, length = 255)
    private var name: String,

    @Enumerated(EnumType.STRING)
    val gender: Gender,

    @Embedded
    val address: Address
): BaseEntity() {
    fun getName() = this.name
    fun setName(name: String) {
        this.name = name
    }
}

주요 어노테이션 설명

1. @Entity

  • 해당 클래스가 JPA 엔티티임을 명시합니다.
  • 필수 어노테이션이며, 생략하면 엔티티로 인식되지 않습니다.

2. @Table

  • 엔티티가 매핑될 데이터베이스 테이블을 지정합니다.
  • name 속성을 통해 테이블 이름을 설정할 수 있습니다.

3. @Id와 @GeneratedValue

  • @Id: 해당 필드를 엔티티의 기본 키로 설정합니다.
  • @GeneratedValue: 기본 키 생성 전략을 지정합니다.
    • GenerationType.IDENTITY: 데이터베이스에 의존하여 기본 키를 생성합니다.

4. @Column

  • 데이터베이스 테이블의 컬럼과 매핑될 필드를 설정합니다.
  • 주요 속성:
    • name: 컬럼 이름 지정
    • nullable: 컬럼이 null을 허용할지 여부
    • unique: 유일 값 여부 설정
    • length: 문자열 길이 제한

5. @Enumerated

  • Enum 타입을 매핑할 때 사용합니다.
  • EnumType.STRING: Enum의 이름을 데이터베이스에 저장합니다.
  • EnumType.ORDINAL: Enum의 순서를 정수로 저장합니다.
    • 하지만 값이 변경될 경우 문제가 생길 수 있으므로 STRING 사용을 권장합니다.

6. @Embedded

  • 다른 클래스를 포함하여 값 타입으로 매핑할 때 사용합니다.
  • @Embeddable이 선언된 클래스를 포함해야 합니다.

7. @SQLDelete 및 @SQLRestriction

    • @SQLDelete: 삭제 동작을 커스터마이징합니다. 실제 데이터 삭제 대신 deleted_at 값을 업데이트합니다.
    • @SQLRestriction: 논리 삭제된 데이터가 조회되지 않도록 제한 조건을 설정합니다.

 

Address와 Gender

1. Embedded 타입: Address

package com.ryan.kotlinspirngjpa.jpa.entity

import jakarta.persistence.Embeddable

@Embeddable
data class Address(
    val address: String,
    val roadAddress: String,
    val detailAddress: String,
    val postCode: String,
    val doorCode: String,
)
  • 값 타입으로 활용할 수 있으며, 테이블 컬럼으로 매핑됩니다.

2. Enum 타입: Gender

package com.ryan.kotlinspirngjpa.jpa.entity

enum class Gender(value: String) {
    MAN("남"),
    WOMAN("여자")
}
  • Enum은 우리가 생각하는 데이터베이스에 enum type과 동일합니다.

 

 

@MappedSuperclass와 공통 엔티티 정의

@MappedSuperclass는 JPA에서 엔티티 클래스 간 공통 필드를 정의하기 위한 어노테이션입니다. 상속받는 엔티티 클래스에서 공통 필드를 재사용할 수 있도록 지원하며, 실제 데이터베이스 테이블에는 매핑되지 않습니다. 이를 통해 코드 중복을 최소화하고 일관성을 유지할 수 있습니다.

 

package com.ryan.kotlinspirngjpa.jpa.entity

import jakarta.persistence.*
import java.time.Instant

@MappedSuperclass
abstract class BaseEntity {

    @Column(name = "created_at", nullable = false, updatable = false)
    val createdAt: Instant = Instant.now()

    @Column(name = "updated_at", nullable = false)
    var updatedAt: Instant = Instant.now()
        protected set

    @Column(name = "deleted_at")
    val deletedAt: Instant? = null

    @PreUpdate
    fun onUpdate() {
        this.updatedAt = Instant.now()
    }
}

 

 

  • @MappedSuperclass
    • 이 어노테이션은 공통적으로 사용할 엔티티 속성을 정의할 때 사용됩니다.
    • 데이터베이스 테이블에는 매핑되지 않으며, 이를 상속받는 엔티티 클래스의 테이블에만 필드가 매핑됩니다.
  • @Column
    • @Column을 통해 필드와 데이터베이스 컬럼을 매핑합니다.
    • created_at은 레코드 생성 시간을 저장하며, updatable = false로 설정해 이후 수정되지 않도록 제한합니다.
    • updated_at은 마지막 업데이트 시간을 저장하며, protected set으로 설정해 외부에서 직접 변경하지 못하게 보호합니다.
    • deleted_at은 소프트 삭제(Soft Delete) 구현 시 사용됩니다.
  • @PreUpdate
    • JPA에서 제공하는 라이프사이클 콜백 메서드 어노테이션입니다.
    • 엔티티가 업데이트되기 직전에 실행됩니다.
    • 여기서는 onUpdate() 메서드를 통해 updatedAt 필드를 자동으로 갱신합니다.
    • Spring-data-jpa를 활용하면 Auditing을 사용할 수 있지만 순수 JPA에서는 다음과 같이 사용해야합니다.

 

이번 시간에는 JPA에서 Entity를 정의하는 방법에 대해 알아봤습니다. 실제 실습을 통해 진행해보시는 걸 추천드리겠습니다.

 

Github

https://github.com/Ryan-Sin/kotlin-spring-jpa/tree/feature/entity

 

GitHub - Ryan-Sin/kotlin-spring-jpa: 코프링 환경에서 기본 jpa부터 spring-data-jpa를 사용하는 방법에 대해

코프링 환경에서 기본 jpa부터 spring-data-jpa를 사용하는 방법에 대해 학습합니다. - Ryan-Sin/kotlin-spring-jpa

github.com