기본키 매핑
@Id @GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
직접 할당
: @Id만 사용
자동 생성(@GeneratedValue)
- IDENTITY: 기본 키 생성을 데이터베이스에 위임
- 주로 MySQL, PostgreSQL, SQL Server에서 사용 (ex. MySQL의 AUTO_ INCREMENT)
- JPA는 보통 트랜잭션 커밋 시점에 INSERT SQL 실행
- AUTO_INCREMENT는 DB에 INSERT SQL을 실행한 이후에 ID 값을 알 수 있음
- 따라서 em.persist() 시점에 즉시 INSERT SQL 실행하고 DB에서 식별자를 조회
- SEQUENCE: 데이터베이스 시퀀스 오브젝트 사용
- 데이터베이스 시퀀스는 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트 (ex. 오라클 시퀀스)
- IDENTITY 전략과는 다르게 일반적인 flush 시점을 가짐 (자바 레벨에서 insert를 하기 전에 식별자 값을 명확하게 알 수 있기 때문에 트랜젝션 종료 직전 flush가 이루어짐)
- 주로 오라클, PostgreSQL, H2 데이터베이스에서 사용
@SequenceGenerator 필요
- name: 식별자 생성기 이름 (필수)
- sequenceName: 데이터베이스에 등록되어 있는 시퀀스 이름 (기본값: hibernate_sequence)
- initialValue: DDL 생성 시에만 사용됨, 시퀀스 DDL을 생성할 때 처음 시작하는 수를 지정 (기본값: 1)
- allocationSize: 시퀀스 한 번 호출에 증가하는 수
- 성능 최적화에 사용됨
- 주의: 데이터베이스 시퀀스 값이 하나씩 증가하도록 설정되어 있으면 이 값을 반드시 1로 설정해야 함 (기본값: 50)
- catalog, schema: 데이터베이스 catalog, schema 이름
@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;
...
}
- TABLE: 키 생성용 테이블 사용, 모든 DB에서 사용
- 키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉내내는 전략
- 모든 데이터베이스에 적용 가능하나 성능 문제
@TableGenerator 필요
- AUTO: 방언에 따라 자동 지정, 기본값
권장하는 식별자 전략
- 기본 키 제약 조건: null이 아님, 유일해야 함, 변하면 안됨
- 미래까지 위 조건을 만족하는 자연키는 찾기 어려우므로 비즈니스와 연관이 없는 대리키(대체키)를 사용하자.
- 권장: Long형 + 대체키 + 키 생성 전략을 사용
- 엔티티를 처음 생성하는 시점에는 값이 없으므로 null 필요 -> (참조형 사용)
SEQUENCE 전략과 최적화
- SEQUENCE 전략은 em.persist()하는 시점에서 데이터베이스에서 ID만 조회해올 수 있음
- 하지만 em.persist()를 할 때마다 네트워크를 이용하면 성능 이슈가 발생할 수 있지않을까?
- 이러한 문제점을 해결하기 위하여 하이버네이트는 allocationSize라는 옵션을 지원하여 시퀀스를 한 번에 여러 개 호출할 수 있으며 이는 동시성 문제도 해결