IT/JPA & Hibernate
[JPA] 기본키 자동 생성 전략(Primary Key)
Bamdule
2021. 5. 10. 11:26
1. Goal
1) 기본키 매핑 방법
2) 기본키 자동 생성 전략 4가지
2. 기본키 매핑 방법
@Entity
public class User {
@Id
private Long id;
}
기본키로 지정하고 싶은 변수에 @Id 어노테이션을 선언하면 해당 컬럼이 기본키로 지정됩니다.
3. 기본키 자동 생성 전략 4가지
기본키를 자동으로 생성하려면 @GeneratedValue(strategy = GenerationType.AUTO) 어노테이션을 기본키 변수 위에 선언해주면 됩니다. 기본키 자동 생성 전략은 4 가지가 있으며 전략속성을 생략하면 AUTO 속성으로 지정됩니다.
1) AUTO
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
}
dialect 값에 따라서 기본키 자동 생성 전략이 지정됩니다. ex) mysql : auto_increment, oracle : sequence ...
2) IDENTITY
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
기본키 생성을 데이터베이스에 위임해 줍니다. 주로 MySQL, PostgreSQL, SQL Server, DB2에서 사용하며, AUTO_INCREMENT를 이용해 기본키를 생성합니다.
JPA는 보통 commit 시점에서 모아둔 쿼리들을 DB로 전송합니다. 그런데 AUTO_INCREMENT는 Insert 시 기본키 값이 생성됩니다. AUTO_INCREMENT 사용 시 commit을 하지 않으면 기본키 값을 알 수 없다는 말인데, 이러한 경우 해당 기본키 값을 참조하는 로직이 있거나 영속성 객체를 만들 때 문제가 생깁니다. 그래서 AUTO_INCREMNT를 사용하면 예외적으로 persist 시점에 바로 DB로 쿼리를 전송해 PK 값 생성 후 객체에 저장합니다.
단점으로는 Insert 쿼리를 모아서 한번에 DB로 전송하는 것이 불가능합니다.
3) SEQUENCE
@Entity
@SequenceGenerator(
name = "USER_SEQ_GENERATOR",
sequenceName = "USER_SEQ", // 시퀸스 명
initialValue = 1, // 초기 값
allocationSize = 1 // 미리 할당 받을 시퀸스 수
)
public class User {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USER_SEQ_GENERATOR")
private Long id;
}
// create sequence USER_SEQ start with 1 increment by 1
# 키 생성 및 초기화
create table USER_SEQ (
next_val bigint
) engine=InnoDB
insert into USER_SEQ values ( 1 )
# 키 조회
select
next_val as id_val
from
USER_SEQ for update
# 키 업데이트
update
USER_SEQ
set
next_val= ?
where
next_val=?
데이터베이스 시퀀스는 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트입니다.
(오라클, PostgreSQL, DB2, H2, MariaDB (10.3 버전 이상) 에서 사용가능)
단점은 persist 시 next sequence를 DB에서 발급 받으며, 이는 잦은 DB 호출로 인한 성능 저하로 연결될 수 있습니다.
그래서 allocationSize 속성을 통해 최대한 DB호출을 줄여야합니다.
장점은 쓰기지연을 통해 SQL 쿼리를 commit시 한번에 DB로 전송해 DB 호출을 최소화할 수 있습니다.
속성 | 설명 | 기본 값 |
name | 식별자 생성기 이름 | 필수 |
sequenceName | 데이터베이스에 등록할 sequence 명 | hibernate_sequence |
initalValue | sequence 초기 값 | 1 |
allocationSize | sequence 호출 시 증가하는 수, jpa는 sequence를 증가 시키다가 할당 받은 sequence를 모두 소모하면 db에 접근하여 sequence를 할당 받을 만큼 증가 시킨다. (성능 최적화를 위해 사용됨) |
50 |
catalog, schema | 데이터베이스 catalog, schema 이름 |
4) TABLE
@Entity
@TableGenerator(
name = "USER_SEQ_GENERATOR",
table = "MY_SEQUENCES",
pkColumnValue = "USER_SEQ",
allocationSize = 1
)
public class User {
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "USER_SEQ_GENERATOR")
private Long id;
}
create table MY_SEQUENCES (
sequence_name varchar(255) not null,
next_val bigint,
primary key (sequence_name)
) engine=InnoDB
insert into MY_SEQUENCES(sequence_name, next_val) values ('USER_SEQ',0)
# 키 조회
select
tbl.next_val
from
MY_SEQUENCES tbl
where
tbl.sequence_name=? for update
# 키 업데이트
update
MY_SEQUENCES
set
next_val=?
where
next_val=?
and sequence_name=?
모든 데이터베이스에서 사용이 가능하며, 키 생성 전용 테이블을 생성해서 키 값을 관리합니다.
최적화되지 않은 테이블에서 키를 생성하기 때문에 성능상의 이슈가 발생할 수 있습니다. 그래서 상용 서비스에서 사용하지 않는 것이 좋습니다.
참조 : 인프런 - 자바 ORM 표준 JPA 프로그래밍 - 기본편 (김영한님)