기본키 매핑 어노테이션 정리 @Id, @GeneratedValue, @SequenceGenerator, @TableGenerator

2021. 1. 18. 15:20JPA/JPA

기본키 매핑은 직접할당과 자동할당 방법으로 나뉜다.

 

@Id

  • 직접할당.
  • 엔티티의 기본키 필드에 값을 직접 넣어 등록한다.

@GeneratedValue

  • 자동할당
속성값 설명 대표DBMS
strategy = GenerationType.IDENTITY 기본키 생성을 데이터베이스에 위임.  MYSQL
strategy = GenerationType.SEQUENCE 시퀀스 사용, @SequenceGenerator 필요(시퀀스 생성) ORACLE
strategy = GenerationType.TABLE 키 생성용 테이블 사용, @TableGenerator 필요 모든 DBMS
strategy = GenerationType.AUTO 데이터베이스 방언에 따라 자동 지정(기본값)  

1. IDENTITY 전략

  • IDENTITY 전략은 기본키 생성을 데이터베이스에 위임한다.
  • jpa 입장에서는 엔티티를 영속 상태에 만들기 위해선, 기본키를 먼저 알아야한다.
  • 따라서 em.persist() 시점에 쓰기 지연을 하지않고 바로 쿼리를 DB에 날려 데이터를 등록하고 식별자를 리턴받는다.
  • 주로 MySQL, PostgreSQL, SQL Server, DB2에서 사용
 (예: MySQL의 AUTO_ INCREMENT) 

2. SEQUENCE 전략

  • SEQUENCE 전략 역시 엔티티를 영속성 컨텍스트에 등록하기 위해선 기본키를 알아야한다.
  • 따라서 em.persist() 시점에 시퀀스를 조회하는 쿼리를 DB에 날려 시퀀스의 nextValue를 받고 영속성 컨텍스트에 등록한다.
  • 오라클, PostgreSQL, DB2, H2 데이터베이스에서 사용 

SEQUENCE 전략 매핑 예시

@Entity
@SequenceGenerator(name = “MEMBER_SEQ_GENERATOR",
				   sequenceName = “MEMBER_SEQ", //매핑할 데이터베이스 시퀀스 이름
                   initialValue = 1,
                   allocationSize = 1) 
public class Member {
	@Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE,
    				generator = "MEMBER_SEQ_GENERATOR")
    private Long id;
}

@SequenceGenerator

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

allocationSize의 작동방법

  1. 최초 persist() 호출시 데이터베이스의 시퀀스 nextValue를 두번 호출하여 시작값과 끝값을 가져온다.
  2. 어플리케이션에서 시작값이 끝값이 될때까지 시퀀스를 메모리에서 할당해준다.
  3. 시퀀스를 끝값까지 전부 사용하게 되면 다시 시퀀스를 호출하는데, 여기서 jpa는 allocationSize를 보고 다음 시작값을 계산한다. 끝값 = 현재값 + allocationSize, 시작값 = 끝값 - (allocationSize - 1)
  4. 2번과 3번을 반복한다.

allocaitionSize 설정시 주의할 점

allocaitionSize의 기본값은 50이다. 그런데 만약 실제 데이터베이스의 시퀀스 증가값은 1일때 어떤 일이 벌어질까? 위의 작동방법대로라면, 3번 동작 즉, 두번째 시작값을 계산할때 시작값이 음수가 된다. 그리고 시작값부터 시퀀스가 계속 할당되고 끝값으로 가게되면 언젠가는 이미 존재하는 시퀀스를 참조하게 되어 에러가 발생하게 된다.

고로, allocaitionSize를 설정할때는 실제 데이터베이스의 증가값을 고려하여 시작값이 음수가 되지 않게 고려하며 성능 최적화를 해야한다.

3. TABLE 전략

  • 키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉내내는 전략
  • 장점: 모든 데이터베이스에 적용 가능 
  • 단점: 성능 -> 성능때문에 권장하지 않는다.

TABLE 전략 매핑 예시

create table MY_SEQUENCES (
	sequence_name varchar(255) not null,
    next_val bigint,
    primary key ( sequence_name )
)
@Entity
@TableGenerator(name = "MEMBER_SEQ_GENERATOR",
        table = "MY_SEQUENCES",
        pkColumnValue = "MEMBER_SEQ",
        allocationSize = 1) 
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE,
            generator = "MEMBER_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) 유니크 제약 조건을 지정할 수 있다.  

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

상속관계 매핑  (0) 2021.01.19
연관관계 매핑  (0) 2021.01.19
컬럼 매핑 어노테이션 정리 @Column, @Temporal, @Enumerated, @Lob, @Transient  (0) 2021.01.18
@Entity  (0) 2021.01.17
스키마 자동 생성  (0) 2021.01.17