직접 할당 전략
기본 키를 직접 할당하려면 @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 전략이 선택되면 시퀀스나 키 생성요 테이블을 미리 만들어 두어야 한다. 만약 스키마 자동 생성 기능을 사용한다면 하이버네이트가 기본값을 사용해서 적절한 시퀀스나 키 생성용 테이블을 만들어 줄 것이다.