개발/Java

[JPA] PK Mapping

Floodnut 2023. 2. 12. 15:39

PK 매핑

@Id 를 통해서 기본키를 매핑한다.

별도의 추가 어노테이션이 없다면 값을 직접 할당해야한다.

@GeneratedValue 를 통해서 값을 자동으로 할당해줄 수 있다.

이 어노테이션에서 속성 값으로 strategy 를 설정해줄 수 있다.


IDENTITY 전략

GenerationType.IDENTITY 의 경우 DB에 생성을 위임한다.

DB INSERT 시점에서 값을 설정한다. 즉, DB에 트랜잭션이 반영된 후에 ID 값을 알 수 있다.

하지만 영속성 컨텍스트에서 이를 관리하기 위해서는 PK 값이 존재해야 한다.

따라서, commit 시점이 아닌 persist 시점에 쿼리를 전달한다.

JDBC 내부적으로 INSERT 시점에 반환 값을 확인할 수 있어 SELECT 쿼리가 발생하지는 않는다.

 CREATE TABLE `table` (
      `id` bigint generated by default as identity,
      `name` varchar(255) NOT NULL,
      PRIMARY KEY (id)
  )

  INSERT INTO
      `table`(id, name)
  VALUES
      (null, ?); // -> id 값이 JPA 에서 NULL로 입력.

Sequence 전략

GenerationType.SEQUENCE의 경우 DB에 생성을 위임한다.

ORACLE의 SEQUENCE 와 같은 형태에 주로 적용된다.

/* HIBERNATE_SEQUENCE 객체를 생성해서 1부터 값을 증가시킴 */
CALL NEXT VALUE FOR HIBERNATE_SEQUENCE

INSERT INTO
     table(id, name)
VALUES
     (?, ?);

만일 테이블마다 다른 시퀀스를 쓰고싶다면?

시퀀스는 DB 시퀀스 객체에서 관리하기에 persist 시점에 DB에 접근해서 시퀀스 값을 가져온다.

  • @SequenceGenerator 를 통해서 테이블마다 시퀀스를 정의하면 된다.
/* 시퀀스 제네레이터 생성 */ 
@SequenceGenerator(name = "member_seq_generator", // 제네레이터 명 
    sequenceName = "member_seq")
public class Member { 

    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, 
        generator = "member_seq_generator") //시퀀스 제네레이터 지정 
    private Long id; 
    ...
}

Table 전략

테이블 매핑 전략을 사용하고 싶다면?

@TableGenerator 를 통해서 키 생성 전용 테이블을 생성하고 지정하면 된다.

단, 성능 상의 단점이 있다.

/* 제네레이터 생성 */ 
@TableGenerator(name = "member_seq_generator", // 제네레이터 명 
    table = "my_sequences", //테이블 명 
    pkColumnValue = "member_seq") //pk 명 
public class Member {

    @Id 
    @GeneratedValue(strategy = GenerationType.TABLE, 
        generator = "member_seq_generator") //제네레이터 지정 
    private Long id;
    ...
}

매핑 전략의 단점과 성능 개선

시퀀스, 테이블 전략 모두 DB 접근을 통해야만 pk를 확인할 수 있다.

이에 대한 성능 하락을 개선할 수 있는 방법이 있다.

initialValueallocationSize 속성을 이용한다.

allocationSize 는 기본 값이 50으로 이 사이즈 만큼 DB에 미리 할당한다.

allocationSize 단위 만큼 메모리 상에서 관리하므로 그만큼 네트워크 부하가 줄게 된다.


PK 제약 조건

PK 제약 조건은 NOT NULL , 변하지 않아야 하는 특성을 가진다.

이를 만족시키는 키를 찾기가 어렵다.

따라서, 대체키와 키 생성 전략을를 추가적으로 함께 사용하는 것이 좋다.