JVM/JPA

JPA 키 생성 전략

kyoulho 2023. 6. 10. 19:47

직접 할당 전략

기본 키를 직접 할당하려면 @Id만 매핑하면 된다

@Id
private Long id;

 

적용 가능 자바 타입

  • 자바 기본형
  • 자바 래퍼형
  • String
  • java.util.Date
  • java.sql.Date
  • java.math.BigDecimal
  • java.math.BigInteger

 

 

IDENTITY 전략

기본 키 생성을 데이터베이스에 위임하는 전략이다.

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

엔티티를 데이터베이스에 저장한 후에 식별자를 조회해서 엔티티의 식별자를 할당한다. 때문에 이 전략은 persist 메소드 호출 시 즉시 INSERT SQL이 데이터베이스에 전달되어 트랜잭션을 지원하는 쓰기 지연이 동작하지 않는다.

JDBC3에 추가된 Statement.getGeneratedKeys()를 사용하면 데이터 저장과 동시에 생성된 기본키 값도 얻어 올 수 있다. 하이버네이트는 이 메소드를 사용해서 데이터베이스와 한 번만 통신한다.

 

SEQUENCE 전략

데이터베이스 시퀀스는 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트다. SEQUENCE 전략은 이 시퀀스를 사용해서 기본 키를 생성한다. 오라클, PostgreSQL, DB2, H2에서 사용할 수 있다.

@Entity
@SequenceGenerator( //필드 위에 사용해도 된다.
        name = "BOARD_SEQ_GENERATOR",
        sequenceName = "매핑할 데이터베이스 시퀀스 이름",
        initialValue = 1,
        allocationSize = 1
)
public class Board {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE,
            generator = "BOARD_SEQ_GENERATOR")
    private Long id;
}

persist 메소드 호출 시 데이터베이스 시퀀스를 사용해서 식별자를 조회한다. 그리고 조회한 식별자를 엔티티에 할당한 후에 엔티티를 영속성 콘텍스트에 저장한다. 이후 트랜잭션을 커밋해서 플러시가 일어나면 엔티티를 데이터베이스에 저장한다.

 

@SequenceGenerator

속성 기능
name 식별자 생성기 이름
sequenceName 데이터베이스에 등록되어 있는 시퀀스 이름
initialValue DDL 생성 시에만 사용됨. 시퀀스 DDL을 생성할 때 처음 시작하는 수를 지정한다.
기본값 1
allocationSize 시퀀스 한 번 호출에 증가하는 수로 성능 최적화에 사용된다.
JPA가 생성하는 데이터베이스 시퀀스는 기본값이 50이다.
데이터베이스 시퀀스 값이 하나씩 증가하도록 설정되어 있다면 이 값을 반드시 1로 설정해야 한다.
catalog 데이터베이스 catalog 이름
schema 데이터베이스 schema 이름

 

 

TABLE 전략

키 생성 전용 테이블을 하나 만들고 여기에 이름과 값으로 사용할 컬럼을 만들어 데이터베이스 시퀀스를 흉내내는 전략이다.

 

TABLE 전략 키 생성 DDL

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

 

TABLE 전략 매핑 코드

@Entity
@TableGenerator(
        name = "BOARD_SEQ_GENERATOR",
        table = "MY_SEQUENCES",
        pkColumnValue = "BOARD_SEQ", allocationSize = 1
)
public class Board {
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE,
            generator = "BOARD_SEQ_GENERATOR")
    private Long id;
}

 

@TableGenerator

속성 기능 기본값
name 식별자 생성기 이름 필수
table 키생성 테이블명 hibernate_sequences
pkColumnName 시퀀스 컬럼명 sequence_name
valueColumnName 시퀀스 값 컬럼명 next_val
pkColumnValue 키로 사용할 값 이름 엔티티 이름
initialValue 초기 값, 마지막으로 생성된 값이 기준이다. 0
allocationSize 시퀀스 한 번 호출에 증가하는 수 (성능 최적화에 사용됨) 50
catalog, schema 데이터베이스 catalog, schema 이름  
uniqueConstraints(DDL) 유니크 제약 조건을 지정할 수 있다.  

 

SEQUECE 전략과 TABLE 전략의 최적화

 두 전략은 모두 시퀀스를 통해 식별자를 조회하는 추가 작업이 필요하다. 따라서 데이터베이스와 2번 또는 3번 통신한다는 단점이 있다.

 JPA는 시퀀스에 접근하는 횟수를 줄이기 위해 @SequenceGenarator.allocationSize를 사용한다. allocationSize 값이 50이면 데이터베이스에 시퀀스를 한 번에 50 증가 시킨 다음 메모리에서 식별자를 하나씩 증가시키며 할당한다. 그리고 51이 되면 데이터베이스 시퀀스 값을 100으로 증가시킨 다음 51~100까지 메모리에서 식별자를 할당한다.  이 최적화 방법은 시퀀스 값을 선점하므로 여러 JVM이 동시에 동작해도 기본 키 값이 충돌하지 않는 장점이 있다.

 이러한 방법은 hibernate.id.new_generator_mappings 속성을 true로 설정해야 한다. 이 속성을 적용하지 않으면 하이버네이트가 과거에 사용하던 방법으로 키 생성을 최적화하는데 데이터베이스 시퀀스 값이 1이면 애플리케이션에서 1~50까지 사용하는 방식이다.

 

 hibernate.id.new_generator_mappings = true

DB SEQUENCE JVM
1 1
51 2
51 3
... ...
51 51
100 52

 

 hibernate.id.new_generator_mappings = false

DB SEQUENCE JVM
1 1 ~ 50
2 51 ~ 100
3 101 ~ 150
... ...

 

AUTO 전략

 데이터베이스 방언에 따라 IDENTITY, SEQUENCE, TABLE 전략 중 하나를 자동으로 선택한다. 오라클은 SEQUENCE, MySQL은 IDENTITY를 사용한다.

 이 전략을 사용할 때 SEQUENCE나 TABLE 전략이 선택되면 시퀀스나 키 생성요 테이블을 미리 만들어 두어야 한다. 만약 스키마 자동 생성 기능을 사용한다면 하이버네이트가 기본값을 사용해서 적절한 시퀀스나 키 생성용 테이블을 만들어 줄 것이다.

'JVM > JPA' 카테고리의 다른 글

@Temporal  (0) 2023.06.11
@Enumerated  (0) 2023.06.11
@Column  (0) 2023.06.11
@Entity  (0) 2023.06.10
@Table  (0) 2023.06.10