티스토리 뷰

JPA

기본 키(Primary Key) 매핑 전략

Jaime.Lee 2019. 10. 1. 18:26

기본 키 매핑 전략

Hibernate에서 지원하는 기본 키(Primary Key) 매핑 전략은 아래와 같습니다.

  • 직접 할당
  • IDENTITY
  • SEQUENCE
  • TABLE
  • AUTO

하나씩 방법을 살펴본 뒤 JPA 기술의 핵심인 영속성과의 상관관계를 알아보도록 하겠습니다.

직접 할당 전략

기본 키를 직접 할당하려면 @Id 어노테이션을 사용하면 됩니다.

@Id
private String id;

@Id는 아래와 같은 타입에 매핑할 수 있습니다.

  • primitive type
  • wrapper type
  • String
  • java.util.Date
  • java.sql.Date
  • java.math.BigDecimal
  • java.math.BigInteger

식별자 없이 저장할 경우 hibernate 기준으로 PersistenceException이 발생합니다.

IDENTIFY 전략

기본 키 생성을 데이터베이스에 위임하는 전략으로 주로 MySQL, PostgresSQL, SQL Server 등에서 사용합니다.
@GeneratedValue 어노테이션에 strategy 속성 값을 GenerationType.IDENTITY로 지정하여 사용합니다.

@Entity
@Data
public class IdEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
}

datasource를 H2 데이터베이스로 설정했을 경우 아래와 같은 스키마를 로그로 확인할 수 있습니다.

Hibernate: 
    create table IdEntity (
        id bigint generated by default as identity,
        primary key (id)
    )

생성한 entity를 다시 조회했을 때는 아래와 select 쿼리가 생성되고 해당 객체를 출력하면 id 값을 확인할 수 있습니다.

Hibernate: 
    /* select
        i 
    from
        IdEntity i */ select
            identity0_.id as id1_0_ 
        from
            IdEntity identity0_
IdEntity(id=1)

데이터베이스에서 생성한 기본 키를 사용하기 때문에 키 값을 얻어오기 위한 조회가 추가로 발생합니다.

SEQUENCE 전략

데이터베이스가 생성하는 유일한 시퀀스 값을 사용하여 기본 키를 생성합니다. oracle, postgresSQL, H2 등에서 사용할 수 있습니다.

@GeneratedValue 어노테이션에 strategy속성 값을 GenerationType.SEQUENCE로 지정하여 사용합니다.

import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
@Data
public class IdEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;
}

어플리케이션 실행시 자동으로 생성된 스키마 로그는 아래와 같습니다.

Hibernate: 
    create table IdEntity (
        id bigint not null,
        primary key (id)
    )
Hibernate: 
    create sequence hibernate_sequence start with 1 increment by 1

추가로 @SequenceGenerator 어노테이션을 사용하여 시퀀스를 직접 지정하여 생성할 수 있습니다.

import lombok.Data;

import javax.persistence.*;

@Entity
@Data
@SequenceGenerator(
        name = "ID_SEQ_GENERATOR",
        sequenceName = "ID_SEQ",
        initialValue = 1,
        allocationSize = 1
)
public class IdEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;
}

이 방식은 IDENTITY 전략과는 다르게 저장할 때 먼저 데이터베이스에 시퀀스를 사용하여 식별자를 조회합니다.

Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
        into
            IdEntity
            (id) 
        values
            (?)

TABLE 전략

키 생성 전용 테이블을 만들어 데이터베이스 시퀀스와 유사한 기능을 제공합니다. 시퀀스를 제공하지 않는 데이터베이스도 사용할 수 있으므로 개발환경과 배포환경이 상이한 경우 사용하기 좋습니다만 테이블을 미리 생성해줘야하는 약간의 번거로움이 있습니다.

database 테이블을 먼저 생성한 뒤,

create table id_sequence (
    sequence_name varchar(255) not null,
    next_val bigint,
    primary key ( sequence_name )
)

@TableGenerator 어노테이션을 이용해 시퀀스 용 테이블과 매핑시켜 줍니다.

import lombok.Data;

import javax.persistence.*;

@Entity
@Data
@TableGenerator(
        name = "ID_SEQ_GENERATOR",
        table = "id_sequence",
        pkColumnValue = "ID_SEQ",
        allocationSize = 1
)
public class IdEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;
}

 

AUTO 전략

데이터베이스의 방언에 따라 IDENTITY, SEQUENCE, TABLE 전략 중 하나를 자동으로 선택합니다. Oracle을 사용할 경우 SEQUENCE 전략을, MySQL을 사용할 경우 IDENTITY를 사용합니다.

@GeneratedValue 어노테이션의 strategy 속성을 GenerationType.AUTO로 지정하여 사용합니다.

import lombok.Data;

import javax.persistence.*;

@Entity
@Data
public class IdEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
}

필자는 테스트 환경에서 H2를 사용는데 이 때 SEQUENCE를 채택하는 것을 확인하였습니다.

Hibernate: 
    create table IdEntity (
        id bigint not null,
        primary key (id)
    )
Hibernate: 
    create sequence hibernate_sequence start with 1 increment by 1

데이터베이스 설정에 자신없는 저 같은(?) 분들이 사용하시기 좋을 것 같습니다.

개발 환경에서는 스키마 자동 생성 기능을 사용하지만 그렇지 않은 경우에는 이미 데이터베이스 스키마가 존재할 것이기 때문에 해당 데이터베이스 방언 및 스키마에 맞게 설정해주시면 되겠습니다.

 

기본 키 매핑과 영속성(Persistance)과의 관계를 같이 포스팅하려고했는데 그러려면 사전에 JPA의 P에 대해 한 번 다루고 넘어가야 할 것 같습니다. 다음에 영속성에 대해 다룬 뒤 관계에 대해 짤막하게 포스팅하려고 합니다.

'JPA' 카테고리의 다른 글

객체와 데이터베이스의 체계와 한계  (0) 2020.04.02
SQL의 문제점  (0) 2020.04.01
JPA를 공부하는 이유  (2) 2020.03.31
JPA 데이터베이스 스키마 자동 생성  (0) 2019.09.30
JPA 매핑 어노테이션 (@Entity, @Table)  (0) 2019.09.30
댓글