
JPA가 제공하는 데이터베이스 기본 키 생성은 아래와 같다.
1. 직접할당
: 기본 키를 어플리케이션에 직접 할당.
: @ID만 사용하는 경우가 이에 해당한다.
2. 자동할당(@GeneratedValue)
: 대리 키방식 사용 - Oracel의 sequence, MySQL의 auto_increment
IDENTITY전략: 기본 키 생성을 DB에 위임하는 전략
주로 MySQL, PostgreSQL, SQL Server, DB2에서 사용
@Entity
public class Member {
@Id, @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
IDENTITY 전략은 MySQL의 auto_increment의 작동 방식과 유사하기 때문에 DB에서 값을 저장한 후 기본키 값을 구할 수 있다.
🔍 영속성 컨텍스트에서 관리 되기 위해선, 기본키 값을 갖고 있어야 한다.
다만, IDENTITY 전략을 사용하면 em.persist(em);시점에 기본키가 없는 상태이기 때문에 영속성 컨텍스트에 저장 할 수 없다.
따라서, @GeneratedValue(strategy = GenerationType.IDENTITY)를 사용할 때는 예외적으로 em.persist(em); 후 commit()을 한다.
❗️ 쓰기 지연 동작하지 않음!
DB SEQUENCE는 유일한 값을 순서대로 생성하는 DB Object이다.
SEQUENCE 전략은 이 SEQUENCE를 사용해서 기본 키를 생성한다.
주로 Oracle, PostgreSQL, DB2, H2에서 사용
// 시퀀스 DDL
CREATE TABLE MEMBER (
ID BIGINT NOT NULL PRIMARY KEY,
DATA VARCHAR(255)
)
// 시퀀스 생성
CREATE SEQUENCE MEMBER_SEQ START WITH 1 INCREMENT BY 1;
// 시퀀스 매핑 코드
@Entity
@SequenceGenerator(
name = "MEMBER_SEQ_GEN",
sequenceName = "MEMBER_SEQ", //데이터베이스 시퀀스 이름
initialValue = 1, allocationSize = 1)
public class Member{
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "MEMBER_SEQ_GEN")
/* @SequenceGenerator 해당 위치에 사용해도 됨. */
private Long id;
//생략
}
❗️ SEQUENCE는 IDENTITY 전략과 같지만 내부 동장 방식은 다르다.
SEQUENCE는 em.persist(entity);를 호출 할 때 먼저 DB에 SEQUENCE를 이용하여 식별자를 조회한다. 그리고 조회된 식별자를 엔티티에 할당 후 영속성 컨텍스트에 저장한다.
IDENTITY는 엔티티를 DB에 저장 후 식별자를 조회하여 엔티티의 식별자에 할당한다.
| 속성 | 기능 | 기본값 |
|---|---|---|
| name | 식별자 생성시 이름 | 필수 값 |
| sequenceName | DB에 등록되어 있는 시퀀스명 | hibernate_sequences |
| initialValue | DDL 생성 시에만 사용 | 1 |
| allocationSize | 시퀀스 한 번 호출에 증가하는 수(성능 최적화에 사용) | 50 |
| catalog, schema | 데이터베이스 catalog, schema 이름 |
TABLE 전략은 기본 키 생성 전용 TABLE을 하나 만들고 여기에 이름과 값으로 사용할 컬럼을 만들어 DB SEQUENCE를 흉내내는 전략이다.
❗️ 장점 : 모든 DB에 적용 가능하다.
❗️ 단점 : 성능이 떨어진다.
// TABLE 전략 키 생성 DDL
create table CUSTOM_SEQUENCE(
sequence_name varchar(255) not null ,
next_val bigint,
primary key ( sequence_name )
)
// TABLE 전략 매핑 코드
@Entity
@TableGenerator(
name = "MEMBER_SEQ_GENERATOR",
table = "CUSTOM_SEQUENCE",
pkColumnValue = "MEMBER_SEQ", allocationSize = 1)
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.TABLE,
generator = "MEMBER_SEQ_GENERATOR")
private Long id;
//생략
}
| 속성 | 설명 | 기본값 |
|---|---|---|
| name | 식별자 생성시 이름 | 필수 |
| table | 키생성 테이블명 | hibernate_sequences |
| pkColumnName | 시퀀스 컬럼명 | sequence_name |
| valueColumnName | 시퀀스 값 컬럼명 | next_val |
| pkColumnValue | 기본 키로 사용할 값 이름 | 엔티티 이름 |
| initialValue | 초기 값 | 0 |
| allocationSize | 시퀀스 한 번 호출에 증가하는 수 | 50 |
| catalog, schema | 데이터베이스 catalog, schema 이름 | |
| uniqueConstraints(DDL) | 유니크 제약 조건 |
DB 특징에 따라, IDENTITY, SEQUENCE, TABLE 중 하나 선택하는 전략
❗️ 키 생성전략이 확정되지 않는 개발초기, 프로토타입 개발에 사용
DB에 따른 전략 선택
자연키는 연관된 테이블도 바꿔야하는 참사가 일어날 수 있으므로, 대리키를 권장함.
즉, AUTO_INCREMENT, 임의로 만들어진 키를 사용할 것을 권장한다. (Long형 + 대체키 + 키 생성전략 사용)
👉 (callmeskye님 블로그 이미지입니다.)
velog - callmeskye
velog - conatuseus
개인적으로 공부하며 기록한 내용으로, 틀린 내용이 있는 경우 덧글을 달아주시면 감사하겠습니다. 😍