JPA 기본 키 생성 전략 - xx10222/selab-todo-list GitHub Wiki
@Entity
public class User {
@Id
private Long id;
}
기본키도 저장하고 싶은 변수에 @Id
어노테이션을 선언하면 해당 컬럼이 기본키로 지정된다
기본키를 자동으로 생성하려면
@GeneratedValue(startegy = GenerationType.AUTO)
어노테이션을 기본키 변수 위에 선언하면 된다
기본키 자동 생성 전략은 4가지가 있으며, 전략 속성을 생략하면 AUTO 속성으로 지정된다
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
}
- dialect 값에 따라서 기본키 자동생성 전략이 지정된다
- ex) mysql : auto_increment, oracle : sequence ...
@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_INCREMENT
를 사용하면 예외적으로 persist 시점에 바로 DB로 쿼리를 전송하여 PK 값 생성 후 객체에 저장한다 - 단점으로는 Insert 쿼리를 모아서 한 번에 DB로 전송하는 것이 불가능하다
@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 호출을 최소화할 수 있다
@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=?
- 모든 데이터베이스에서 사용이 가능하며, 키 생성 전용 테이블을 생성해서 키 값을 관리한다
- 최적화되지 않은 테이블에서 키를 생성하기 때문에 성능상의 이슈가 발생할 수 있다
- 그래서 상용 서비스에서 사용하지 않는 것이 좋다