[JPA]

@GeneratedValue (테이블 전략, AUTO 전략)

everydeveloper 2024. 3. 29. 17:33

테이블 전략

테이블 전략은 어떤거야?

테이블 전략(Table Strategy)은 JPA(Java Persistence API)에서 엔티티의 기본 키(primary key)를 생성하기 위해 사용되는 전략 중 하나입니다. 이 전략은 특별한 데이터베이스 시퀀스나 자동 증가(auto-increment) 기능을 사용하지 않고, 대신에 하나 또는 여러 개의 데이터베이스 테이블을 사용하여 엔티티의 기본 키 값을 관리합니다. 이 방법은 모든 종류의 데이터베이스에서 사용할 수 있는 장점이 있으며, 특히 시퀀스나 자동 증가 기능을 지원하지 않는 데이터베이스에서 유용합니다.

테이블 전략의 작동 방식

  1. 키 생성 테이블: JPA는 기본 키 값을 생성하고 저장하기 위한 별도의 테이블을 사용합니다. 이 테이블에는 각 엔티티 타입 또는 엔티티 그룹마다 하나의 행(row)을 할당하고, 해당 행에서 다음에 사용할 기본 키 값을 저장합니다.
  2. 키 값의 증가: 새 엔티티가 영속화될 때마다, JPA는 이 테이블에 접근하여 현재의 기본 키 값을 읽고, 그 값을 엔티티의 기본 키로 할당한 후, 테이블에 저장된 값은 증가시킵니다.
  3. 데이터베이스 독립성: 이 전략은 특정 데이터베이스 기능에 의존하지 않기 때문에, 다양한 데이터베이스 시스템에서 일관된 방식으로 기본 키를 생성할 수 있습니다.

@TableGenerator 어노테이션

테이블 전략을 구현하기 위해 JPA에서는 @TableGenerator 어노테이션을 제공합니다. 이 어노테이션을 사용하여 기본 키 생성용 테이블의 이름, 기본 키 값을 저장할 컬럼 이름, 초기값, 증가 크기 등을 설정할 수 있습니다.

예시

@Entity
public class MyEntity {
    @Id
    @TableGenerator(name = "entity_gen", table = "ID_GEN", pkColumnName = "GEN_NAME",
        valueColumnName = "GEN_VAL", pkColumnValue = "MY_ENTITY_ID", initialValue = 1, allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "entity_gen")
    private Long id;
    // 엔티티의 다른 필드들...
}

위 예시에서 @TableGenerator는 기본 키를 생성하기 위한 설정을 제공하며, @GeneratedValue와 함께 사용되어 엔티티의 id 필드에 대한 기본 키 생성 전략으로 테이블 전략을 지정합니다.

장단점

  • 장점: 모든 데이터베이스 시스템에서 사용 가능하며, 특정 데이터베이스 기능에 의존하지 않습니다.
  • 단점: 기본 키 값을 생성하기 위해 추가적인 테이블 접근이 필요하므로, 성능이 다소 저하될 수 있습니다. 또한, 기본 키 생성을 위한 테이블 관리가 필요합니다.

테이블 전략은 그 유연성으로 인해 시퀀스나 자동 증가 기능을 지원하지 않는 데이터베이스 환경에서 특히 유용한 기본 키 생성 방법입니다.

이거는 시퀀스를 관리하는 하나의 테이블을 하나 더 생성해서 관리하는 방식이야? 내가 원하는 컬럼값에 바로 직접 올리는 것이 아니라 TableGenerator로 테이블 생성해서 테이블 명으로 맵핑해서 쓰는 방식 같네

네, 맞습니다. 테이블 전략(Table Strategy)은 시퀀스나 자동 증가(auto-increment) 기능을 사용하지 않고, 대신에 특별히 지정된 하나 또는 여러 개의 데이터베이스 테이블을 이용하여 엔티티의 기본 키 값을 관리하고 생성하는 방식입니다. 이 방식에서 사용하는 테이블은 기본 키 값을 생성하기 위한 목적으로만 사용되며, 이를 위해 @TableGenerator 어노테이션을 통해 구성됩니다.

테이블 전략의 주요 구성 요소:

  • 키 생성용 테이블: 이 테이블은 기본 키 생성을 위해 사용되며, 일반적으로 하나의 행(row)이 하나의 엔티티 타입 또는 그룹을 대표하게 됩니다. 이 행에는 다음에 사용할 기본 키 값과, 그 값을 증가시키기 위한 정보(증가 크기 등)가 포함됩니다.
  • @TableGenerator 어노테이션: 이 어노테이션을 사용하여 키 생성 테이블의 이름, 키 값이 저장될 컬럼의 이름, 초기값, 증가 크기 등을 설정합니다. 또한, 어떤 엔티티 또는 엔티티 그룹이 해당 키 생성 테이블의 어떤 행과 맵핑될 것인지를 지정할 수 있습니다.

작동 방식:

  1. 엔티티가 영속화될 때, JPA는 설정된 키 생성용 테이블에 접근하여 해당 엔티티 타입 또는 그룹에 대응하는 행의 현재 키 값을 조회합니다.
  2. 조회된 키 값은 엔티티의 기본 키 값으로 할당되며, 이후 키 생성용 테이블의 해당 행에 저장된 키 값은 지정된 증가 크기만큼 증가시킵니다.
  3. 이 과정을 통해 각 엔티티는 고유한 기본 키 값을 가지게 되며, 키 값의 중복을 방지할 수 있습니다.

장단점:

  • 장점: 데이터베이스의 종류에 관계없이 일관된 방식으로 기본 키를 생성할 수 있으며, 시퀀스나 자동 증가 기능을 지원하지 않는 데이터베이스에서도 사용할 수 있습니다.
  • 단점: 추가적인 테이블 접근이 필요하기 때문에, 특히 많은 양의 데이터를 빠르게 삽입해야 하는 경우 성능 저하가 발생할 수 있습니다. 또한, 기본 키 생성을 위한 별도의 테이블 관리가 필요합니다.

테이블 전략은 특정한 요구 사항이나 데이터베이스 환경에 따라 선택할 수 있는 유연한 기본 키 생성 방법 중 하나입니다.

AUTO 전략은 무엇이야?

AUTO 전략은 Java Persistence API(JPA)에서 엔티티의 기본 키(primary key) 생성 방식을 지정할 때 사용되는 옵션 중 하나입니다. 이 전략을 사용하면, JPA 구현체는 실행되는 데이터베이스 환경에 따라 자동으로 가장 적합한 기본 키 생성 전략을 선택합니다. 즉, 개발자가 직접 특정 기본 키 생성 전략을 지정하지 않아도, JPA가 실행 중인 데이터베이스의 특성을 고려하여 IDENTITY, SEQUENCE, TABLE 중에서 하나를 선택하여 사용합니다.

AUTO 전략의 특징

  • 데이터베이스 독립성: AUTO 전략은 특정 데이터베이스에 종속되지 않습니다. 이는 다양한 데이터베이스 환경에서 애플리케이션을 이식성 있게 만들고자 할 때 유용합니다.
  • 유연성: 실행 중인 데이터베이스의 기능과 최적화된 전략을 자동으로 활용할 수 있어, 애플리케이션 개발 과정에서 복잡성을 줄일 수 있습니다.
  • 쉬운 구성: 개발자는 기본 키 생성에 대한 구체적인 전략을 신경 쓸 필요 없이, AUTO 전략을 지정하기만 하면 됩니다. 이후 JPA 구현체가 적절한 전략을 선택합니다.

AUTO 전략의 선택 기준

JPA 구현체는 다음과 같은 기준으로 AUTO 전략 하에 사용할 실제 전략을 결정할 수 있습니다:

  • IDENTITY: 주로 MySQL, SQL Server와 같이 데이터베이스가 기본 키 생성을 위한 자동 증가(auto-increment) 기능을 제공할 때 선택됩니다.
  • SEQUENCE: Oracle, PostgreSQL과 같이 시퀀스 객체를 지원하는 데이터베이스에서 주로 사용됩니다. 시퀀스를 사용하여 고유한 값을 생성합니다.
  • TABLE: 시퀀스나 자동 증가 기능을 지원하지 않는 데이터베이스에서 사용될 수 있습니다. 하나 이상의 테이블을 사용하여 기본 키 값을 생성하고 관리합니다.

예시

@Entity
public class ExampleEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    // 엔티티의 다른 필드들...
}

이 예시에서, @GeneratedValue 어노테이션의 strategy 속성에 GenerationType.AUTO가 지정되어 있습니다. 이 경우, JPA 구현체는 실행 중인 데이터베이스 환경을 자동으로 감지하여 가장 적합한 기본 키 생성 전략을 선택하여 사용합니다.

결론

AUTO 전략은 다양한 데이터베이스 환경에서 유연하고 이식성 높은 애플리케이션을 개발하고자 할 때 매우 유용한 옵션입니다. 개발자는 데이터베이스의 특정 기능에 대한 심층적인 이해 없이도, JPA가 자동으로 최적의 기본 키 생성 방법을 선택하도록 할 수 있습니다.

AUTO 전략의 선택 기준이 table로 선택 한다면 테이블도 자동으로 생성해주는 건인가?

아니면 테이블은 미리 TableGenerator으로 미리 지정해 두면 테이블로 지정 할 수 있는 선택지가 되어 주는 것인가?

AUTO 전략이 TABLE을 선택했을 경우의 동작 방식은 JPA 구현체와 구성에 따라 약간 다를 수 있습니다. 그러나 일반적인 경우는 다음 두 가지 중 하나로 설명할 수 있습니다:

  1. 자동 테이블 생성: 대부분의 JPA 구현체는 AUTO 전략이 TABLE 전략을 선택했을 때 필요한 테이블을 자동으로 생성할 수 있습니다. 이 경우, JPA 구현체는 기본 키 생성을 위한 전용 테이블을 만들고, 필요한 메타데이터(예: 현재 키 값, 증가 크기 등)를 관리합니다. 이 테이블은 애플리케이션의 데이터베이스 스키마 초기화 또는 업데이트 과정에서 생성될 수 있으며, 별도의 설정 없이도 기본 키 생성에 사용됩니다.
  2. TableGenerator 설정 사용: 개발자가 명시적으로 TableGenerator 어노테이션을 사용하여 기본 키 생성을 위한 테이블을 미리 지정할 수도 있습니다. 이 방법을 사용하면, 개발자는 테이블의 이름, 키 값을 저장할 컬럼의 이름, 초기값, 증가 크기 등을 직접 지정할 수 있으며, AUTO 전략이 TABLE 전략을 선택할 경우 이 설정을 사용하여 기본 키 값을 생성합니다. 이 경우, 테이블의 구조와 사용 방법은 TableGenerator 어노테이션에 지정된 정보에 따라 결정됩니다.

일반적으로 AUTO 전략은 JPA 구현체가 실행 환경에 가장 적합한 기본 키 생성 전략을 자동으로 선택하도록 합니다. 만약 구현체가 TABLE 전략을 선택했다면, 개발자가 별도로 TableGenerator를 설정하지 않았다면, 구현체는 기본 설정 또는 내부 로직에 따라 필요한 테이블을 자동으로 생성하고 관리할 수 있습니다. 그러나 더 세밀한 제어가 필요하거나 특정 데이터베이스 구조를 따라야 할 경우, TableGenerator를 사용하여 이를 명시적으로 지정할 수 있습니다.

@Column 어노태이션에서 precision, scale 옵션은 어떤거야?

@Column 어노테이션의 precision과 scale 옵션은 Java Persistence API(JPA)에서 소수점 숫자를 다룰 때 사용됩니다. 이 옵션들은 주로 BigDecimal 타입의 필드를 데이터베이스의 소수점 숫자 타입과 매핑할 때 활용됩니다. 이 옵션들을 통해 소수점 숫자의 정밀도와 스케일을 정의할 수 있으며, 이는 데이터베이스에 저장될 숫자의 형태를 미리 지정하는 데 도움이 됩니다.

precision

  • precision은 숫자가 가질 수 있는 최대 자릿수를 정의합니다. 이는 소수점을 포함한 전체 숫자의 길이를 의미합니다. 예를 들어, precision이 5인 경우, 숫자는 최대 99999까지 또는 소수점을 포함하여 123.45처럼 표현될 수 있습니다.

scale

  • scale은 소수점 이하의 자릿수를 정의합니다. 즉, 전체 숫자 중 소수점 아래로 허용되는 최대 자릿수를 지정합니다. 예를 들어, scale이 2인 경우, 숫자는 0.01, 0.99, 123.45와 같이 소수점 이하 두 자리까지만 저장될 수 있습니다.

사용 예시

@Column(precision = 6, scale = 2)
private BigDecimal price;

이 예시에서 price 필드는 최대 6자리의 숫자를 가질 수 있으며, 이 중 소수점 아래 2자리까지 표현될 수 있습니다. 따라서, 1234.56이나 12.34와 같은 값은 유효하지만, 123456.78 또는 123.456은 precision과 scale 설정에 맞지 않기 때문에 문제가 될 수 있습니다.

precision과 scale 옵션은 주로 금융 애플리케이션에서 금액이나 비율을 정확하게 표현해야 할 때 중요합니다. 이를 통해 애플리케이션과 데이터베이스 간에 데이터의 정밀도를 유지하며, 예상치 못한 데이터 손실이나 변형을 방지할 수 있습니다.

@Enumerated는 어떤거야?

@Enumerated 어노테이션은 Java Persistence API(JPA)에서 Java의 열거형(enum) 타입을 데이터베이스의 컬럼과 매핑할 때 사용됩니다. 이 어노테이션을 통해 열거형의 값을 어떻게 데이터베이스에 저장할 것인지를 지정할 수 있으며, 주로 두 가지 저장 방식 중에서 선택할 수 있습니다: EnumType.ORDINAL과 EnumType.STRING.

EnumType.ORDINAL

  • EnumType.ORDINAL을 사용하면, 열거형 상수가 선언된 순서(0부터 시작하는 인덱스)에 따라 데이터베이스에 정수 값으로 저장됩니다. 이 방식의 장점은 저장 공간의 효율성입니다. 그러나 열거형 상수의 순서가 변경되거나 중간에 상수가 추가/삭제되면 데이터의 일관성이 깨질 위험이 있습니다.

EnumType.STRING

  • EnumType.STRING을 사용하면, 열거형 상수의 이름을 문자열로 데이터베이스에 저장합니다. 이 방식은 데이터베이스에서 데이터를 직접 보았을 때 가독성이 높고, 열거형 상수의 순서 변경에 영향을 받지 않는다는 장점이 있습니다. 그러나 ORDINAL에 비해 더 많은 저장 공간을 사용할 수 있습니다.

사용 예시

Java 열거형(enum)을 정의하고, @Enumerated 어노테이션을 사용하여 데이터베이스에 매핑하는 예시입니다.

public enum Status {
    ACTIVE, INACTIVE, DELETED
}

@Entity
public class MyEntity {
    @Id
    private Long id;

    @Enumerated(EnumType.STRING)
    private Status status;
}

이 예시에서는 Status 열거형이 있고, MyEntity 클래스의 status 필드는 Status 열거형을 사용합니다. @Enumerated(EnumType.STRING) 어노테이션을 통해 status 필드의 값을 데이터베이스에 문자열로 저장하도록 지정했습니다. 따라서 status 필드의 값으로 ACTIVE, INACTIVE, DELETED 중 하나가 데이터베이스에 저장됩니다.

@Enumerated 어노테이션을 사용함으로써, 애플리케이션의 코드에서 사용하는 열거형 타입의 값들을 데이터베이스에 효과적으로 저장하고, 애플리케이션과 데이터베이스 간의 타입 일관성을 유지할 수 있습니다.

@Temporal은 무엇이야?

@Temporal 어노테이션은 Java Persistence API(JPA)에서 날짜와 시간을 다룰 때 사용됩니다. Java의 java.util.Date 및 java.util.Calendar 타입의 필드가 데이터베이스의 날짜(date), 시간(time), 또는 타임스탬프(timestamp) 중 어떤 타입으로 매핑될 것인지를 지정할 때 @Temporal 어노테이션을 사용합니다.

@Temporal의 사용 가능한 값:

  • TemporalType.DATE: 이 값은 오직 날짜 정보만 저장합니다 (예: YYYY-MM-DD). 시간 정보는 무시됩니다.
  • TemporalType.TIME: 이 값은 오직 시간 정보만 저장합니다 (예: HH:MM:SS). 날짜 정보는 무시됩니다.
  • TemporalType.TIMESTAMP: 이 값은 날짜와 시간 정보를 모두 저장합니다 (예: YYYY-MM-DD HH:MM:SS).

사용 예시

@Entity
public class MyEntity {
    @Id
    private Long id;

    @Temporal(TemporalType.DATE)
    private Date birthDate;

    @Temporal(TemporalType.TIMESTAMP)
    private Date lastUpdated;
}

이 예시에서 birthDate 필드는 TemporalType.DATE를 사용하여 오직 날짜 정보만 데이터베이스에 저장하도록 지정했습니다. 반면, lastUpdated 필드는 TemporalType.TIMESTAMP를 사용하여 날짜와 시간 정보를 모두 저장하도록 설정했습니다.

주의할 점

  • Java 8 이후로는 java.time 패키지에 포함된 새로운 날짜 및 시간 API(예: LocalDate, LocalDateTime)를 사용하는 것이 권장됩니다. 이 새로운 API는 JPA 2.2 이상에서 @Temporal 어노테이션 없이 직접 사용할 수 있으며, 더 강력하고 유연한 날짜 및 시간 처리 기능을 제공합니다.

@Temporal 어노테이션은 주로 JPA가 날짜 및 시간 타입을 어떻게 데이터베이스에 저장할지 제어할 필요가 있을 때, 구버전 Java에서 사용됩니다.

'[JPA]' 카테고리의 다른 글

필드 접근, 프로퍼티 접근  (1) 2024.04.06
@Id, @SequenceGenerator  (0) 2024.03.28
@Enumerated, @Temporal 어노테이션  (0) 2024.03.04