[JPA] Entity Mapping #2

Harry park·2022년 6월 17일
0

JPA

목록 보기
3/8

기본 키 매핑


JPA가 제공하는 데이터베이스 기본 키 생성은 아래와 같다.
1. 직접할당
: 기본 키를 어플리케이션에 직접 할당.
: @ID만 사용하는 경우가 이에 해당한다.
2. 자동할당(@GeneratedValue)
: 대리 키방식 사용 - Oracel의 sequence, MySQL의 auto_increment

자동할당 전략

IDENTITY 전략

IDENTITY전략: 기본 키 생성을 DB에 위임하는 전략

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

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

IDENTITY 전략은 MySQLauto_increment의 작동 방식과 유사하기 때문에 DB에서 값을 저장한 후 기본키 값을 구할 수 있다.

🔍 영속성 컨텍스트에서 관리 되기 위해선, 기본키 값을 갖고 있어야 한다.
다만, IDENTITY 전략을 사용하면 em.persist(em);시점에 기본키가 없는 상태이기 때문에 영속성 컨텍스트에 저장 할 수 없다.
따라서, @GeneratedValue(strategy = GenerationType.IDENTITY)를 사용할 때는 예외적으로 em.persist(em);commit()을 한다.

❗️ 쓰기 지연 동작하지 않음!


SEQUENCE 전략

DB SEQUENCE는 유일한 값을 순서대로 생성하는 DB Object이다.
SEQUENCE 전략은 이 SEQUENCE를 사용해서 기본 키를 생성한다.

주로 Oracle, PostgreSQL, DB2, H2에서 사용

// 시퀀스 DDL
CREATE TABLE MEMBER (
	ID BIGINT NOT NULL PRIMARY KEY,
   DATA VARCHAR(255)
)

// 시퀀스 생성
CREATE SEQUENCE MEMBER_SEQ START WITH 1 INCREMENT BY 1;
// 시퀀스 매핑 코드
@Entity
@SequenceGenerator(
 name = "MEMBER_SEQ_GEN",
 sequenceName = "MEMBER_SEQ", //데이터베이스 시퀀스 이름
 initialValue = 1, allocationSize = 1)
public class Member{

 @Id
 @GeneratedValue(strategy = GenerationType.SEQUENCE,
                 generator = "MEMBER_SEQ_GEN")
/* @SequenceGenerator 해당 위치에 사용해도 됨. */
 private Long id;
 //생략
 }

❗️ SEQUENCEIDENTITY 전략과 같지만 내부 동장 방식은 다르다.
SEQUENCEem.persist(entity);를 호출 할 때 먼저 DBSEQUENCE를 이용하여 식별자를 조회한다. 그리고 조회된 식별자를 엔티티에 할당 후 영속성 컨텍스트에 저장한다.
IDENTITY는 엔티티를 DB에 저장 후 식별자를 조회하여 엔티티의 식별자에 할당한다.

@SequenceGenerator 속성

속성 기능 기본값
name 식별자 생성시 이름 필수 값
sequenceName DB에 등록되어 있는 시퀀스명 hibernate_sequences
initialValue DDL 생성 시에만 사용 1
allocationSize 시퀀스 한 번 호출에 증가하는 수(성능 최적화에 사용) 50
catalog, schema 데이터베이스 catalog, schema 이름

TABLE 전략

TABLE 전략은 기본 키 생성 전용 TABLE을 하나 만들고 여기에 이름과 값으로 사용할 컬럼을 만들어 DB SEQUENCE를 흉내내는 전략이다.

❗️ 장점 : 모든 DB에 적용 가능하다.
❗️ 단점 : 성능이 떨어진다.

// TABLE 전략 키 생성 DDL
create table CUSTOM_SEQUENCE(
	sequence_name varchar(255) not null ,
   	next_val bigint,
  	primary key ( sequence_name )
)
// TABLE 전략 매핑 코드
@Entity
@TableGenerator(
 name = "MEMBER_SEQ_GENERATOR",
 table = "CUSTOM_SEQUENCE",
 pkColumnValue = "MEMBER_SEQ", allocationSize = 1)
public class Member {

 @Id
 @GeneratedValue(strategy = GenerationType.TABLE,
                 generator = "MEMBER_SEQ_GENERATOR")
 private Long id;
 //생략
 }

@TableGenerator 속성

속성 설명 기본값
name 식별자 생성시 이름 필수
table 키생성 테이블명 hibernate_sequences
pkColumnName 시퀀스 컬럼명 sequence_name
valueColumnName 시퀀스 값 컬럼명 next_val
pkColumnValue 기본 키로 사용할 값 이름 엔티티 이름
initialValue 초기 값 0
allocationSize 시퀀스 한 번 호출에 증가하는 수 50
catalog, schema 데이터베이스 catalog, schema 이름
uniqueConstraints(DDL) 유니크 제약 조건

AUTO 전략

DB 특징에 따라, IDENTITY, SEQUENCE, TABLE 중 하나 선택하는 전략

❗️ 키 생성전략이 확정되지 않는 개발초기, 프로토타입 개발에 사용

DB에 따른 전략 선택

  • ORACLE == SEQUENCE
  • MySQL == IDENTITY
  • H2 == SEQUENCE

권장하는 식별자 전략

대리키 사용

자연키는 연관된 테이블도 바꿔야하는 참사가 일어날 수 있으므로, 대리키를 권장함.
즉, AUTO_INCREMENT, 임의로 만들어진 키를 사용할 것을 권장한다. (Long형 + 대체키 + 키 생성전략 사용)

이유

  1. 자연키는 유일하지 않음.
    👉 유선 전화를 사용하다 핸드폰만 사용하게 되는 경우 nul
  2. 환경이 변할 수 있다.
    👉 한국에서 주민등록번호를 사용하지 않게 되는 경우

정리

👉 (callmeskye님 블로그 이미지입니다.)


참고사이트

velog - callmeskye
velog - conatuseus


개인적으로 공부하며 기록한 내용으로, 틀린 내용이 있는 경우 덧글을 달아주시면 감사하겠습니다. 😍

profile
Jr. Backend Engineer

0개의 댓글