[JPA] 기본 키 생성 전략(IDENTITY, SEQUENCE, TABLE)

GilLog·2021년 7월 18일
8

JPA

목록 보기
4/8

🙆‍♂️ import 🙇‍♂️

자바 ORM 표준 JPA 프로그래밍


기본 키 할당 전략

JPA가 제공하는 DB 기본 키 할당 전략직접 할당 방식, 자동 생성 방식 두 가지이다.

이 중 직접 할당 방식은 Application에서 기본 키를 직접 할당하는 방식이다.

자동 생성 방식은 대리 키를 사용하는 방식으로 IDENTITY, SEQUENCE, TABLE 네 가지가 있다.

해당 방식들은 사용하는 DB에 의존한다.
MySQLIDENTITY 사용, OracleSEQUENCE 사용


직접 할당 방식

직접 할당 방식을 사용할 경우 Entity를 생성할 때 Key Column에 @Id만 사용해 주어도 된다.

@Id
private long id;

@Id가 적용 가능한 Java Type은 아래와 같다.

  • Java 기본형(int, double, long ...)
  • Java Wrapper 형
  • String
  • java.util.Date
  • java.sql.Date
  • java.math.BigDecimal
  • java.math.BigInteger

해당 전략em.persist()로 Entity를 저장 하기 전,

Application에서 직접 기본 키를 할당해주어야 한다.

EntityManagerFactory emf = Persistence.createEntityManagerFactory("JPA");

EntityManager em = emf.createEntityManager();

User user = new User();
user.setName("gillog");
user.setId(1);

em.persist(user);

자동 생성 방식

자동 생성 방식을 사용할 경우 @Id@GeneratedValue를 사용한다.

IDENTITY

기본 키 생성을 DB에 위임하는 전략이다.

MySQL과 같이 Sequence를 제공하지 않고, AutoIncrement 기능을 제공해,

기본 키 값을 자동으로 생성하는 DBMS에서 사용한다.

주로 MySQL, PostgreSQL, SQL Server, DB2에서 사용한다.

아래와 같이 사용할 수있다.

@Id
@GeneratedValue=strategy = GenerationType.IDENTITY)
private long id;

IDENTITY전략은 Data를 DB에 Insert한 후 기본 키 값을 조회할 수 있다.

Entity에 식별자 값을 할당하려면 JPA는 추가로 DB를 조회해야 하는데,

HibernateJDBC3에 추가된 Statement.getGeneratedKeys()를 사용DB와 한번만 통신한다.
해당 메소드는 Data를 저장하면서, 생성된 기본 키 값을 가져온다.


하지만 Entity가 영속 상태가 되려면 식별자가 반드시 필요한데,

DB에 저장해야만 식별자를 구할 수 있는 방식이므로,

em.persist()호출 즉시 Insert Query를 DB에 전달해 식별자를 가져오므로,

Transaction을 지원하는 쓰기 지연 방식이 동작하지 않는다.

SEQUENCE

해당 방식DB Sequence를 사용해 기본 키를 할당하는 방식으로,

Sequence 전략을 지원하는 Oracle, PostgreSQL, DB2, H2 DB에서 주로 사용한다.

아래와 같이 DB에서 Seqeunce를 생성 후에 사용할 수 있다.

CREATE SEQUENCE USER_SEQ START WITH 1 INCREMENT BY 1;

후에 Entity를 생성할 때 @SequenceGenerator Annotation을 사용한다.

@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;
    
}

@SequenceGenerator Annotation에서 사용 가능한 속성들은 아래와 같다.

속성설명기본 값
name식별자 생성기 이름없음 지정 필수.
sequenceNameDB에 등록되어 있는 Sequence이름hibernate_sequence
initalValue(DDL)DDL 생성시에만 사용, Sequence DDL 생성시 처음 시작 value를 설정1
allocationSizeSequence 한번 호출시 증가하는 수(성능 최적화에 사용)50
catalog, schemaDB catalog, schema 이름

allocationSize와 성능 최적화

allocationSize가 기본값이 50이므로 해당 속성을 1로 설정하지 않을 시,

sequence 호출 시마다 50씩 증가한다.

기본 값이 50인 이유JPA가 sequence에 접근 횟수를 줄이기 위함이다.

allocationSize에 설정 값 만큼 한 번에 sequence를 증가 시키고, 그만큼 Memory에 seqeunce 값을 할당한다.

그 후 Memory를 활용해 JVM안에서 sequence를 할당 한다.

이 방법은 sequenc를 선점하여 다른 여러 JVM이 동시 동작해도 기본 키 값이 충돌하지 않는 장점이 있다.


IDENTITY VS SEQUENCE

IDENTITY 전략먼저 Entity를 DB에 저장한 후에,

식별자를 조회해 Entity의 식별자로 할당하는 전략이다.


SEQUENCE 전략em.persist() 호출 전에 먼저 DB Sequence를 먼저 조회한다.

그 후 조회한 식별자를 Entity에 할당한 후 Entity를 영속상태로 저장한다.

그 후 TransactionCommit하여 Flush가 발생할 때 해당 Entity를 DB에 저장한다.

TABLE

해당 전략Key 생성 Table을 사용하는 전략이다.

Key 생성 전용 Table을 생성하고, name, value로 사용할 Column을 생성하여

DB Sequence를 흉내내는 전략이다.

아래와 같이 Key 생성 전용 Table을 생성한 후,

CREATE TABLE CUSTOM_SEQUENCE {
	sequence_name varchar(255) not null
    , next_val bigint
    , primary key (sequence_name)
}

@TableGenerator Annotation을 사용해 Entity를 Mapping한다.

@Entity
@TableGenerator(
	name = "USER_SEQ_GENERATOR"
    , table = "CUSTOM_SEQUENCE"
    , pkColumnValue = "USER_SEQ"
    , allocationSize = 1
)
public class User {

    @Id
    @GeneratedValue(
    	strategy = GenerationType.TABLE
    	, generator = "USER_SEQ_GENERATOR"
    )
    private long id;
    
}

해당 전략은 SEQUENCE 전략과 내부 동작 방식이 같다.

pkColumnValue로 설정한 USER_SEQ라는 SEQUENCE NAMECUSTOM_SEQUENCE Table의 sequence_name Column에 생성한 후,
next_val Column의 값이 증가한다.
값이 없으면 JPA가 Insert하면서 초기화하므로 미리 값을 넣어두지 않아도 됨

@TableGenerator에서 사용 가능한 속성들은 아래와 같다.

속성설명기본 값
name식별자 생성기 이름없음 지정 필수.
table키 생성 테이블 명hibernate_sequences
pkColumnName시퀀스 컬럼 명sequence_name
valueColumnName시퀀스 값 컬럼 명next_val
pkColumnValue키로 사용할 값 이름Entity 이름
initialValue초기 값, 마지막 생성된 값이 기준0
allocationSzie시퀀스 호출시 증가 값(성능 최적화에 사용)50
catalog, schemaDB catalog, schema 이름
uniqueConstraints(DDL)유니크 제약 조건을 지정

TABLE 전략은 값을 조회하면서 Select Query를, 그 후 값 증가를 위해 Update Query를 사용한다.

SEQUENCE 전략과 비교해 DB와 한번 더 통신하는 단점이 있고,

SEQUENCE 전략의 최적화와 같이 allocationSize를 사용해 최적화 한다.

AUTO

AUTO 전략선택한 DB 방언에 따라 자동으로 IDENTITY, SEQUENCE, TABLE 전략을 자동으로 선택한다.
DB의 종류도 많고, 기본 키 생성 방식도 다양하기에

해당 전략은 DB를 변경해도 Code 수정을 하지 않아도 되는 장점과,

Key 생성 전략이 정해지지 않은 개발 초기 단계프로토타입 개발 시에 편리하게 사용할 수있다.

하지만 만약 AUTOSEQUENCETABLE전략이 선택 될 경우,

Sequence나 키 생성 Table을 미리 생성해 두어야 한다.

만약 DDL 자동 생성 기능을 사용한다면, Hibernate가 기본 값을 사용해 알아서 생성해준다.

profile
🚀 기록보단 길록을 20.10 ~ 22.02 ⭐ Move To : https://gil-log.github.io/

1개의 댓글

comment-user-thumbnail
2022년 12월 27일

Jpa hibernate를 공부하다가 자동키할당 방식에서 트러블을 만나서 슈팅하던중 hibernate의 auto방식이 변경된 부분을 찾아서 좀더 알아보다가 찾은 글이였는데 auto sequence identify table에 대한 정리가 너무 잘되어있어서 많은 도움, 공부가 되었습니다. 감사합니다

답글 달기