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
개인적으로 공부하며 기록한 내용으로, 틀린 내용이 있는 경우 덧글을 달아주시면 감사하겠습니다. 😍