3 분 소요

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 벤더를 변경해도 전략을 수정하지 않아도 되지만, SEQUENCETABLE 전략을 선택한다면 sequence나 키 테이블을 생성해두어야 함을 주의하자.
    (그런데 JPA ddl-auto 기능을 사용하면 hibernate가 알아서 시퀀스 테이블을 생성해준다.)

🚨 주의
하이버네이트를 무조건 믿어선 안된다!
Mysql의 경우 AUTO로 설정하면 당연히 IDENTITY 전략을 취할 것이라 생각하고 생략하거나,
추후 DBMS 종류 변경을 고려해 그냥 AUTO로 사용하는 경우가 있는데,
버전에 따라 선택되는 전략이 달라질 수 있으므로, 직접 DBMS에 맞는 전략을 지정해주도록 한다.

+) Hibernate 5부터 MySQL에서의 GenerationType.AUTOIDENTITY가 아닌 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.



💛 개인 공부 기록용 블로그입니다. 👻

맨 위로 이동하기

태그:

카테고리:

업데이트: