[JPA] 엔티티 매핑 2 - 기본키 매핑

조성우·2024년 3월 20일

JPA - 공부

목록 보기
5/16
post-thumbnail

기본키 매핑

@Id @GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

직접 할당

: @Id만 사용

자동 생성(@GeneratedValue)

  • IDENTITY: 기본 키 생성을 데이터베이스에 위임
    • 주로 MySQL, PostgreSQL, SQL Server에서 사용 (ex. MySQL의 AUTO_ INCREMENT)
    • JPA는 보통 트랜잭션 커밋 시점에 INSERT SQL 실행
    • AUTO_INCREMENT는 DB에 INSERT SQL을 실행한 이후에 ID 값을 알 수 있음
    • 따라서 em.persist() 시점에 즉시 INSERT SQL 실행하고 DB에서 식별자를 조회
  • SEQUENCE: 데이터베이스 시퀀스 오브젝트 사용
    • 데이터베이스 시퀀스는 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트 (ex. 오라클 시퀀스)
    • IDENTITY 전략과는 다르게 일반적인 flush 시점을 가짐 (자바 레벨에서 insert를 하기 전에 식별자 값을 명확하게 알 수 있기 때문에 트랜젝션 종료 직전 flush가 이루어짐)
    • 주로 오라클, PostgreSQL, H2 데이터베이스에서 사용
    • @SequenceGenerator 필요
      • name: 식별자 생성기 이름 (필수)
      • sequenceName: 데이터베이스에 등록되어 있는 시퀀스 이름 (기본값: hibernate_sequence)
      • initialValue: DDL 생성 시에만 사용됨, 시퀀스 DDL을 생성할 때 처음 시작하는 수를 지정 (기본값: 1)
      • allocationSize: 시퀀스 한 번 호출에 증가하는 수
        • 성능 최적화에 사용됨
        • 주의: 데이터베이스 시퀀스 값이 하나씩 증가하도록 설정되어 있으면 이 값을 반드시 1로 설정해야 함 (기본값: 50)
      • catalog, schema: 데이터베이스 catalog, schema 이름
    @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;
        ...
    }
  • TABLE: 키 생성용 테이블 사용, 모든 DB에서 사용
    • 키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉내내는 전략
    • 모든 데이터베이스에 적용 가능하나 성능 문제
    • @TableGenerator 필요
  • AUTO: 방언에 따라 자동 지정, 기본값

권장하는 식별자 전략

  • 기본 키 제약 조건: null이 아님, 유일해야 함, 변하면 안됨
  • 미래까지 위 조건을 만족하는 자연키는 찾기 어려우므로 비즈니스와 연관이 없는 대리키(대체키)를 사용하자.
  • 권장: Long형 + 대체키 + 키 생성 전략을 사용
    • 엔티티를 처음 생성하는 시점에는 값이 없으므로 null 필요 -> (참조형 사용)

SEQUENCE 전략과 최적화

  • SEQUENCE 전략은 em.persist()하는 시점에서 데이터베이스에서 ID만 조회해올 수 있음
  • 하지만 em.persist()를 할 때마다 네트워크를 이용하면 성능 이슈가 발생할 수 있지않을까?
  • 이러한 문제점을 해결하기 위하여 하이버네이트는 allocationSize라는 옵션을 지원하여 시퀀스를 한 번에 여러 개 호출할 수 있으며 이는 동시성 문제도 해결

0개의 댓글