[JPA] 기본키 생성 전략 - GenerationType
JPA에서 Entity 객체를 정의할 때 @Id
속성을 함께 정의해야 한다.
Id를 정의할 때 “직접 할당하는 방법”과 “데이터베이스가 자동으로 할당해주는 방법”이 있다.
1. 직접 할당
@Id
어노테이션만으로 id를 지정한다.
2. 자동 생성
@Id
와@GeneratedValue
를 같이 사용한다.GenerationType
옵션으로 전략을 지정한다.
GenerationType의 종류
1) AUTO
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
}
- DB 벤더에 따라 자동으로
IDENTITY
,SEQUENCE
,TABLE
中 택 1 hibernate.dialect
에 설정된 DB 방언 종류에 따라, 하이버네이트가 자동으로 전략을 선택하게끔 위임한다.- DB 벤더를 변경해도 전략을 수정하지 않아도 되지만,
SEQUENCE
나TABLE
전략을 선택한다면 sequence나 키 테이블을 생성해두어야 함을 주의하자.
(그런데 JPA ddl-auto 기능을 사용하면 hibernate가 알아서 시퀀스 테이블을 생성해준다.)
🚨 주의
하이버네이트를 무조건 믿어선 안된다!
Mysql의 경우AUTO
로 설정하면 당연히IDENTITY
전략을 취할 것이라 생각하고 생략하거나,
추후 DBMS 종류 변경을 고려해 그냥AUTO
로 사용하는 경우가 있는데,
버전에 따라 선택되는 전략이 달라질 수 있으므로, 직접 DBMS에 맞는 전략을 지정해주도록 한다.
+) Hibernate 5부터 MySQL에서의GenerationType.AUTO
는IDENTITY
가 아닌TABLE
을 기본 시퀀스 전략으로 가져간다.
2) IDENTITY
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
- 기본 키 생성을 데이터베이스에 위임한다.
- 주로 MySQL, PostgreSQL, SQL Server, DB2에서 사용한다. (예: MySQL의
AUTO_ INCREMENT
) - IDENTITY 전략은,
em.persist()
로 객체를 영속화 시키는 시점에 곧바로 insert 쿼리가 DB로 전송되고, 거기서 반환받은 식별자 값을 가지고 1차 캐시에 엔티티를 등록시켜 관리한다.
💥 객체를 저장할 때 벌어지는 일 💥
JPA는 보통의 경우에, 트랜잭션이 commit 되는 시점에 쓰기 지연 저장소에 모아놓은 SQL을 한 번에 DB로 전송하며 실행한다.
이렇게 해야 어플리케이션과 DB 사이에 네트워크를 오가는 횟수가 줄어들고 성능면에서 이득을 볼 수 있기 때문이다.
하지만 IDENTITY 전략은 DB에 기본키 생성을 위임하므로, Mysql의 경우 AUTO_INCREMENT를 활용하여 생성하는데,
이 때, JPA 입장에선 DB에 INSERT SQL를 실행하기 전엔 도저히 AUTO_INCREMENT되는 값을 알 수 없으므로,persist()
시점에 insert 쿼리가 실행되는 것이다.
(영속성 컨텍스트로 엔티티를 관리하려면 1차 캐시에 Id값을 key 값으로 들고 있어야 하기 때문에)
3) SEQUENCE
@Entity
@SequenceGenerator(
name = "MEMBER_SEQ_GENERATOR", // 실제 @Id 필드에서 참조할 이름
sequenceName = "MEMBER_SEQ", // 실제 데이터베이스에 생성되는 시퀀스 객체 이름
initialValue = 1, allocationsSize = 50 // allocationsSize : DB에서 가져오는 시퀀스 호출에 증가하는 값의 크기
)
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "MEMBER_SEQ_GENERATOR")
private Long id;
}
- DB의 sequence 객체를 이용해 유일한 값을 순서대로 생성한다. 즉 특정 DB 벤더에 의존적이다.
- sequence를 사용하는 Oracle, PostgreSQL, DB2, H2 등의 DB에서 사용한다.
@SequenceGenerator
(시퀀스를 생성하는 어노테이션)과 함께 사용할 수 있다.
만약 sequence 객체를 사용하지 않는 DB 벤더를 이용할 경우 Sequence를 관리할 객체(테이블)을 생성한다. (단 jpa ddl auto 설정이 되어있어야 한다.)
sequenceName 으로 시퀀스를 분리하여 지정할 수 있고, allocationSize로 한 번에 사용할 시퀀스 덩어리 사이즈를 정해서 최적화 할 수 있다.
@SequenceGenerator
에서 사용 가능한 속성들은 아래와 같다.
속성 | 설명 | 기본 값 |
---|---|---|
name | 식별자 생성기 이름 | 없음 지정 필수. |
sequenceName | DB에 등록되어 있는 Sequence이름 | hibernate_sequence |
initalValue(DDL) | DDL 생성시에만 사용, Sequence DDL 생성시 처음 시작 value를 설정 | 1 |
allocationSize | Sequence 한번 호출시 증가하는 수(성능 최적화에 사용) | 50 |
catalog, schema | DB catalog, schema 이름 |
💥 객체를 저장할 때 벌어지는 일 💥
IDENTITY 전략과 다른점이 존재한다.
해당 전략은 단순히 sequence 값만 시퀀스 객체에서 조회해오면 되기에, 엔티티 테이블에 해당 객체를 바로 insert 할 필요가 없다.
이말인 즉슨,
객체를 save() 메서드로 저장을 할 때 id 값을 채우기 위해 select 문이 실행되고, 트랜잭션이 끝나는 COMMIT 시점에 insert 문이 실행된다.
4) TABLE
@Entity
@TableGenerator(
name = "MEMBER_SEQ_GENERATOR", // 실제 @Id 필드에서 참조할 이름
table = "MY_SEQUENCES", //시퀀스 생성용 테이블 이름
pkColumnName = "sequence_name", //MY_SEQUENCES 테이블에 생성할 필드이름 (시퀀스네임)
pkColumnValue = "MEMBER_SEQ", //SEQ_NAME이라고 지은 칼럼명에 들어가는 값 (키로 사용할 값)
allocationsSize = 50 // allocationsSize : DB에서 가져오는 시퀀스 호출에 증가하는 값의 크기
)
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.TABLE,
generator = "MEMBER_SEQ_GENERATOR")
private Long id;
}
- 키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉내내는 전략이다.
@TableGenerator
(테이블 생성 어노테이션)과 함께 사용할 수 있다.- 이 전략을 사용할 시, jpa ddl auto 설정이 되어 있지 않았다면 해당 시퀀스 테이블 생성이 선행이 되어야한다.
jpa ddl auto 설정이 되어있다면 hibernate가 시퀀스 테이블을 생성한다. - 특정 벤더에 의존적이지 않아 모든 데이터베이스에 적용 가능하나, 성능적인 손해가 있어서 잘 쓰지 않는다.
@TableGenerator
에서 사용 가능한 속성들은 아래와 같다.
속성 | 설명 | 기본 값 |
---|---|---|
name | 식별자 생성기 이름 | 없음 지정 필수. |
table | 키 생성 테이블 명 | hibernate_sequences |
pkColumnName | 시퀀스 컬럼 명 | sequence_name |
valueColumnName | 시퀀스 값 컬럼 명 | next_val |
pkColumnValue | 키로 사용할 값 이름 | Entity 이름 |
initialValue | 초기 값, 마지막 생성된 값이 기준 | 0 |
allocationSzie | 시퀀스 호출시 증가 값(성능 최적화에 사용) | 50 |
catalog, schema | DB catalog, schema 이름 | |
uniqueConstraints(DDL) | 유니크 제약 조건을 지정 |
Ref.
- https://newwisdom.tistory.com/90
- https://devcamus.tistory.com/m/16
- https://velog.io/@gillog/JPA-%EA%B8%B0%EB%B3%B8-%ED%82%A4-%EC%83%9D%EC%84%B1-%EC%A0%84%EB%9E%B5IDENTITY-SEQUENCE-TABLE
💛 개인 공부 기록용 블로그입니다. 👻