객체가 RDB에 매핑될 때 반드시 PK로 사용할 멤버변수를 지정해줘야 한다.

 

이때 @Id 어노테이션을 사용하는데, 이것만 사용할 경우 다른 컬럼들과 똑같이 PK값도 일일히 직접 할당해주게 된다.

보통 PK에 대해서는 이런 식으로 하지 않고 값이 알아서 자동적으로 할당되도록 하는 것이 좋다.

 

이를 위해 @Genera5tedValue 어노테이션을 추가로 사용하는데 여기에 적용되는 여러 가지 옵션이 있다.

그 중 가장 대표적인 방식은 IDENTITY, SEQUENCE 방식이다.

 

 

1. IDENTITY

@Entity 
public class Member { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 
}

PK의 생성을 데이터베이스가 대신 할당하도록 한다. 주로 MySQL에서 사용되는 방식이다.

(오라클은 IDENTITY 지원하지 않음)

IDENTITY 전략을 사용할 때 영속성 컨텍스트는 평소와는 조금 다르게 동작한다.

 

em.persist()로 영속성 컨텍스트에 객체를 저장하게 되면 해당 객체는 영속성 컨텍스트에 있는 1차 캐시 안에서 Key-Value 쌍으로 존재하게 된다.

 

이때 Key = PK, Value = Object의 형태로 존재하게 되는데.. IDENTITY 방식은 엔티티가 실질적으로 DB에 저장되는 순간 DB에서 자동으로 PK값을 할당해주는 방식이다.

하지만 트랜잭션이 커밋되기 전까지 해당 객체에 대한 쿼리는 DB에 적용되지 않는다. 

 

즉, 커밋이 이뤄지기 전까지는 PK를 가질 수 없다는 것. 그런데 영속성 컨텍스트 안에서는 PK-Object의 키밸류 페어로 존재해야 한다.

 

이를 해결하기 위해서 IDENTITY 전략을 사용할 때는 예외적으로 em.persist()를 호출했을 때 즉각적으로 DB에 실제 쿼리를 날려버린다.

 

 

 

2. SEQUENCE

@Entity 
@SequenceGenerator( 
        name = “MEMBER_SEQ_GENERATOR", 
        sequenceName = “MEMBER_SEQ", // 매핑할 데이터베이스 시퀀스 이름
        initialValue = 1, allocationSize = 1) 
public class Member { 
    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, 
            generator = "MEMBER_SEQ_GENERATOR") 
    private Long id; 
}

 

SEQUENCE 전략은 DB의 시퀀스 오브젝트를 사용하여 PK값을 자동할당한다. 주로 오라클 디비에서 사용되는 방식이다.

(MySQL은 SEQUENCE 지원하지 않음)

이를 위해 @SequenceGenerator를 통해 사용할 시퀀스 오브젝트를 직접 생성해줘야 한다.

 

em.persist()를 수행하면 DB의 시퀀스 오브젝트에게서 1차캐시에 Key값으로 저장될 PK값을 할당받아 객체와 함께 영속성 컨텍스트 안에 저장한다.

(이떄 IDENTITY 전략 처럼 DB에 쿼리가 날아가는 것은 아니다)

 

하지만 PK 하나가 필요할 때마다 매번 디비쪽과 네트워크 통신을 하기 때문에 성능에 대한 문제가 있을 수 있다. 이를 방지하기 위해 @SequenceGenerator의 allocationSize 속성이 존재한다.

 

allocationSize는 한 번의 시퀀스 접근을 통해 사용할 수 있는 PK값의 개수를 의미한다.

allocationSize의 디폴트 값은 50인데, 이 경우 한 번의 DB 접근만으로 50개의 PK값을 얻어와 메모리에 저장한 뒤 영속성 컨텍스트에 객체를 저장할 때마다 메모리에서 PK를 하나씩 가져와 할당하는 것이다.

 

이렇게 하면 네트워크 접근 횟수를 비약적으로 줄일 수 있게 된다.

 

시퀀스 동작에 대한 좀 더 자세한 설명은 아래 질문글 링크를 참고

https://www.inflearn.com/questions/116520

 

 

 

 

'김영한님 스프링 강의 정리 > JPA' 카테고리의 다른 글

@ManyToMany를 사용하면 안 되는 이유  (0) 2021.02.24
연관관계 매핑과 관계의 주인  (0) 2021.02.21
Flush에 대해  (0) 2021.02.19
Persistence Context 에 대해  (0) 2021.02.19
JPQL이란?  (0) 2021.02.19

+ Recent posts